Hierarchical query for mulitiple groups - sql

I'd like to generate every month end date between two dates but I need to do that for multiple groups. Simplified example is here:
select last_day(add_months(date '2015-01-01', level - 1)), 1 gr from dual
connect by level <= 12
union all
select last_day(add_months(date '2015-01-01', level - 1)), 2 gr from dual
connect by level <= 12;
Can it be done in single SQL query without union all as I have many groups.
I know I can do it with PL/SQL but just out of curiosity it is possible to do with single SQL statement?
I'd like query like this one:
with d as (
select date '2015-01-01' start_date, date '2015-12-01' end_date, 1 gr from dual
union all
select date '2015-01-01' start_date, date '2015-12-01' end_date, 2 gr from dual
)
select last_day(add_months(start_date, level - 1)) from d
start with start_date = date '2015-01-01'
connect by level <= months_between(end_date, start_date);
but generating results as first query does not cross join

You can use the PRIOR and SYS_GUID() option
WITH d
AS (SELECT DATE '2015-01-01' start_date,
DATE '2015-12-01' end_date,
1 gr
FROM dual
UNION ALL
SELECT DATE '2015-01-01' start_date,
DATE '2015-12-01' end_date,
2 gr
FROM dual)
SELECT gr,
last_day(add_months(start_date, LEVEL - 1)) AS dt
FROM d
START WITH start_date = DATE '2015-01-01'
CONNECT BY LEVEL <= months_between(end_date, start_date)
AND PRIOR gr = gr
AND PRIOR sys_guid() IS NOT NULL
ORDER BY gr,
dt
| GR | DT |
|----|----------------------|
| 1 | 2015-01-31T00:00:00Z |
| 1 | 2015-02-28T00:00:00Z |
| 1 | 2015-03-31T00:00:00Z |
| 1 | 2015-04-30T00:00:00Z |
| 1 | 2015-05-31T00:00:00Z |
| 1 | 2015-06-30T00:00:00Z |
| 1 | 2015-07-31T00:00:00Z |
| 1 | 2015-08-31T00:00:00Z |
| 1 | 2015-09-30T00:00:00Z |
| 1 | 2015-10-31T00:00:00Z |
| 1 | 2015-11-30T00:00:00Z |
| 2 | 2015-01-31T00:00:00Z |
| 2 | 2015-02-28T00:00:00Z |
| 2 | 2015-03-31T00:00:00Z |
| 2 | 2015-04-30T00:00:00Z |
| 2 | 2015-05-31T00:00:00Z |
| 2 | 2015-06-30T00:00:00Z |
| 2 | 2015-07-31T00:00:00Z |
| 2 | 2015-08-31T00:00:00Z |
| 2 | 2015-09-30T00:00:00Z |
| 2 | 2015-10-31T00:00:00Z |
| 2 | 2015-11-30T00:00:00Z |
Demo

I've found one more way but lateral is also not what I was aiming for. Kaushik's answer is what I was looking for.
with data as (
select date '2015-01-01' start_date, date '2015-12-01' end_date, 1 as gr from dual
union all
select date '2015-01-01' start_date, date '2015-12-01' end_date, 2 as gr from dual
),
data_level as(
select start_Date
,end_date
,gr
,months_between(end_date,start_date) + 1 as lvl
from data)
select g from data_level,
lateral(select last_day(add_months(start_date,level - 1)) g
from dual
connect by level <= lvl
);

Related

Sum the total employment time/year for employees / plsql [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
a 'job' table as follow
How do I find the total years of employment for all the employees?
+--------+-----------+-----------------+------------------+
| emplid | record | action | effect dt |
+--------+-----------+-----------------+------------------+
| 1 | 0 | terminate | 8/9/2010 |
| 1 | 0 | hire | 5/6/2006 |
| 1 | 0 | terminate | 3/4/2005 |
| 1 | 0 | hire | 1/1/2003 |
| 1 | 1 | hire | 1/1/2006 |
| 1 | 1 | terminate | 5/5/2004 |
| 1 | 1 | promote | 4/4/2003 |
| 1 | 1 | hire | 3/3/2002 |
| 1 | 1 | terminate | 2/2/2001 |
| 1 | 1 | hire | 1/1/2000 |
| 2 | 0 | rehire | 6/7/2013 |
| 2 | 0 | terminate | 5/6/2011 |
| 2 | 0 | rehire | 3/3/2010 |
| 2 | 0 | terminate | 2/2/2009 |
| 2 | 0 | hire | 1/1/2008 |
+--------+-----------+-----------------+------------------+
If you are using Oracle 12 or later, use MATCH_RECOGNIZE to find pairs of (re)hire/terminate entries and then use MONTHS_BETWEEN to find the duration then group and sum to get the total:
SELECT emplid,
record,
SUM(
MONTHS_BETWEEN(
COALESCE( terminate_dt, SYSDATE ),
hire_dt
) / 12
) AS hire_years
FROM job
MATCH_RECOGNIZE(
PARTITION BY emplid, record
ORDER BY effect_dt
MEASURES
FIRST( hire.effect_dt ) AS hire_dt,
LAST( terminate.effect_dt ) AS terminate_dt
ONE ROW PER MATCH
PATTERN ( hire changes* terminate? )
DEFINE
hire AS hire.action IN ( 'hire', 'rehire' ),
changes AS changes.action NOT IN ( 'hire', 'rehire', 'terminate' ),
terminate AS terminate.action IN ( 'terminate' )
)
GROUP BY
emplid,
record
(Assuming that if an employee has been hired but there is no later termination entry then they are still employed.)
Which, for the sample data:
CREATE TABLE job ( emplid, record, action, effect_dt ) AS
SELECT 1, 0, 'terminate', DATE '2010-09-08' FROM DUAL UNION ALL
SELECT 1, 0, 'hire', DATE '2006-06-05' FROM DUAL UNION ALL
SELECT 1, 0, 'terminate', DATE '2005-04-03' FROM DUAL UNION ALL
SELECT 1, 0, 'hire', DATE '2003-01-01' FROM DUAL UNION ALL
SELECT 1, 1, 'hire', DATE '2006-01-01' FROM DUAL UNION ALL
SELECT 1, 1, 'terminate', DATE '2004-05-05' FROM DUAL UNION ALL
SELECT 1, 1, 'promote', DATE '2003-04-04' FROM DUAL UNION ALL
SELECT 1, 1, 'hire', DATE '2002-03-03' FROM DUAL UNION ALL
SELECT 1, 1, 'terminate', DATE '2001-02-02' FROM DUAL UNION ALL
SELECT 1, 1, 'hire', DATE '2000-01-01' FROM DUAL UNION ALL
SELECT 2, 0, 'rehire', DATE '2013-07-06' FROM DUAL UNION ALL
SELECT 2, 0, 'terminate', DATE '2011-06-05' FROM DUAL UNION ALL
SELECT 2, 0, 'rehire', DATE '2010-03-03' FROM DUAL UNION ALL
SELECT 2, 0, 'terminate', DATE '2009-02-02' FROM DUAL UNION ALL
SELECT 2, 0, 'hire', DATE '2008-01-01' FROM DUAL;
Outputs:
EMPLID | RECORD | HIRE_YEARS
-----: | -----: | ----------------------------------------:
1 | 0 | 6.51344086021505376344086021505376344086
1 | 1 | 18.18784323974512146555157307845479888494
2 | 0 | 9.75773571286340103544404619673436877738
db<>fiddle here

Monthly Snapshot using Date Dimension

I've some columns that I need to bring to a consolidated table(fact). I've a change capture table which captures changes to record everyday which looks like this:
CHG_TABLE:
+--------+-------------------+-----------------------+-----------+-----------+
| Key | Start_Date | End_Date | Value |Record_Type|
+--------+----- -------------+-----------------------+-----------+-----------+
| 1 | 5/25/2019 2.05 | 12/31/9999 00.00 | 800 | Insert |
| 1 | 5/25/2019 2.05 | 5/31/2019 11.12 | 800 | Update |
| 1 | 5/31/2019 11.12 | 12/31/9999 00.00 | 900 | Insert |
| 1 | 5/31/2019 11.12 | 6/15/2019 12.05 | 900 | Update |
| 1 | 6/15/2019 12.05 | 12/31/9999 00.00 | 1000 | Insert |
| 1 | 6/15/2019 12.05 | 6/25/2019 10.20 | 1000 | Update |
| 1 | 6/25/2019 10.20 | 12/31/9999 00.00 | 500 | Insert |
| 1 | 6/25/2019 10.20 | 6/30/2019 11.12 | 500 | Update |
| 1 | 6/30/2019 11.12 | 12/31/9999 00.00 | 3000 | Insert |
| 1 | 6/30/2019 11.12 | 7/15/2019 1.20 | 3000 | Update |
| 1 | 7/15/2019 1.20 | 12/31/9999 00.00 | 7000 | Insert |
+--------+-------------------+-----------------------+-----------+-----------+
During first insert, End_Date is end of time. When new record with new Start_Date and Value is added to the source it's captured as new entry and previous record with same Key is updated with End_Date as Start_Date of new record.
DIM_DATE:
+--------+-------------------+-----------------------+
|DateKey | Month_Start_Date | Month_End_Date |
+--------+-----+-------------+-----------------------+
| 1 | 6/1/2019 | 6/30/2019 |
| 2 | 7/1/2019 | 7/31/2019 |
+--------+-------------------+-----------------------+
I am struggling since I am using DATE dimension which has Month_Start_Date and Month_End_Date.
I want to create a monthly snapshot from this change table which would look like this:
RESULT:
+--------+-------------------+-----------------------+-----------+-----------+
| Key | Month_Start_Date | Month_End_Date |Begin_Value|End_Value |
+--------+-----+-------------+-----------------------+-----------+-----------+
| 1 | 6/1/2019 | 6/30/2019 | 800 | 500 |
| 1 | 7/1/2019 | 7/31/2019 | 500 | 3000 |
+--------+-------------------+-----------------------+-----------+-----------+
Begin_Value : Max(End_Date) < Month_Start_Date
End_Value : Max(End_Date) <= Month_End_Date
The Begin_Value should be most recent value from last month(which is not end of the time) and End_Value should be the most recent value based on Month_End_Date.
How to show above result?
I think you should rethink your logic a bit.
If CHG_TABLE has a 'update' record on July 15th and there is no later change, then that new value should be end value for July.
Assuming (big if) that's correct, then you should just ignore the END_DATE column altogether. If you're able, drop it from your data model. You don't need it.
Instead, create a descending index on CHG_TABLE.START_DATE, like so:
create index chg_table_n1 on chg_table (start_date desc);
Then, you should be able to create your snapshot fairly efficiently like this:
select ct.key,
dd.month_start_date,
dd.month_end_date,
( SELECT value
FROM chg_table ct2
WHERE ct2.key = ct.key
AND ct2.start_date < dd.month_start_date
ORDER BY ct2.start_date DESC
FETCH FIRST 1 ROW ONLY ) first_value,
max(ct.value) keep ( dense_rank last order by ct.start_date ) last_value
from dim_date dd
INNER JOIN chg_table ct ON ct.start_date BETWEEN dd.month_start_date and dd.month_end_date
GROUP BY ct.key, dd.month_start_date, dd.month_end_date;
Hopefully you are on release 12.1 or later for the FETCH FIRST syntax. Otherwise, you'll need to tweak that part to the pre-12.1 equivalent.
FULL EXAMPLE WITH TEST DATA
WITH chg_table ( key, start_date, end_date, value, record_type ) AS
(
SELECT 1,TO_DATE('5/25/2019 2.05','MM/DD/YYYY HH24.MI'),TO_DATE('12/31/9999 00.00','MM/DD/YYYY HH24.MI'), 800, 'Insert' FROM DUAL UNION ALL
SELECT 1,TO_DATE('5/25/2019 2.05','MM/DD/YYYY HH24.MI'),TO_DATE('5/31/2019 11.12','MM/DD/YYYY HH24.MI'), 800, 'Update' FROM DUAL UNION ALL
SELECT 1,TO_DATE('5/31/2019 11.12','MM/DD/YYYY HH24.MI'),TO_DATE('12/31/9999 00.00','MM/DD/YYYY HH24.MI'), 900, 'Insert' FROM DUAL UNION ALL
SELECT 1,TO_DATE('5/31/2019 11.12','MM/DD/YYYY HH24.MI'),TO_DATE('6/15/2019 12.05','MM/DD/YYYY HH24.MI'), 900, 'Update' FROM DUAL UNION ALL
SELECT 1,TO_DATE('6/15/2019 12.05','MM/DD/YYYY HH24.MI'),TO_DATE('12/31/9999 00.00','MM/DD/YYYY HH24.MI'), 1000, 'Insert' FROM DUAL UNION ALL
SELECT 1,TO_DATE('6/15/2019 12.05','MM/DD/YYYY HH24.MI'),TO_DATE('6/25/2019 10.20','MM/DD/YYYY HH24.MI'), 1000, 'Update' FROM DUAL UNION ALL
SELECT 1,TO_DATE('6/25/2019 10.20','MM/DD/YYYY HH24.MI'),TO_DATE('12/31/9999 00.00','MM/DD/YYYY HH24.MI'), 500, 'Insert' FROM DUAL UNION ALL
SELECT 1,TO_DATE('6/25/2019 10.20','MM/DD/YYYY HH24.MI'),TO_DATE('6/30/2019 11.12','MM/DD/YYYY HH24.MI'), 500, 'Update' FROM DUAL UNION ALL
SELECT 1,TO_DATE('6/30/2019 11.12','MM/DD/YYYY HH24.MI'),TO_DATE('12/31/9999 00.00','MM/DD/YYYY HH24.MI'),3000, 'Insert' FROM DUAL UNION ALL
SELECT 1,TO_DATE('6/30/2019 11.12','MM/DD/YYYY HH24.MI'),TO_DATE('7/15/2019 1.20','MM/DD/YYYY HH24.MI'), 3000, 'Update' FROM DUAL UNION ALL
SELECT 1,TO_DATE('7/15/2019 1.20','MM/DD/YYYY HH24.MI'),TO_DATE('12/31/9999 00.00','MM/DD/YYYY HH24.MI'),7000, 'Insert' FROM DUAL ),
dim_date ( datekey, month_start_date, month_end_date ) AS (
SELECT 1, DATE'2019-05-01', DATE'2019-06-01' - INTERVAL '1' SECOND FROM DUAL UNION ALL
SELECT 2, DATE'2019-06-01', DATE'2019-07-01' - INTERVAL '1' SECOND FROM DUAL UNION ALL
SELECT 3, DATE'2019-07-01', DATE'2019-08-01' - INTERVAL '1' SECOND FROM DUAL )
select ct.key,
dd.month_start_date,
dd.month_end_date,
( SELECT value
FROM chg_table ct2
WHERE ct2.key = ct.key
AND ct2.start_date < dd.month_start_date
ORDER BY ct2.start_date DESC
FETCH FIRST 1 ROW ONLY ) first_value,
max(ct.value) keep ( dense_rank last order by ct.start_date ) last_value
from dim_date dd
INNER JOIN chg_table ct ON ct.start_date BETWEEN dd.month_start_date and dd.month_end_date
GROUP BY ct.key, dd.month_start_date, dd.month_end_date;
+-----+------------------+----------------+-------------+------------+
| KEY | MONTH_START_DATE | MONTH_END_DATE | FIRST_VALUE | LAST_VALUE |
+-----+------------------+----------------+-------------+------------+
| 1 | 01-MAY-19 | 31-MAY-19 | | 900 |
| 1 | 01-JUN-19 | 30-JUN-19 | 900 | 3000 |
| 1 | 01-JUL-19 | 31-JUL-19 | 3000 | 7000 |
+-----+------------------+----------------+-------------+------------+
Update - version w/o MAX()..KEEP(), assuming the existence of DIM_PERSON table
select k.key,
dd.month_start_date,
dd.month_end_date,
( SELECT value
FROM chg_table ct2
WHERE ct2.key = k.key
AND ct2.start_date < dd.month_start_date
ORDER BY ct2.start_date DESC
FETCH FIRST 1 ROW ONLY ) first_value,
( SELECT value
FROM chg_table ct2
WHERE ct2.key = k.key
AND ct2.start_date <= dd.month_end_date
ORDER BY ct2.start_date DESC
FETCH FIRST 1 ROW ONLY ) last_value
from dim_date dd
CROSS JOIN dim_person k
GROUP BY k.key, dd.month_start_date, dd.month_end_date;

SQL - Insert multiple rows based on one record with conditions

I need to insert multiple rows based on one record in Table A to Table B. The query needs to grab each day from the start and end date in Table A and check if it is working day. If it's non-working days(weekends), it will not insert into Table B.
Scenario as below:
Table A:
+ LID + Start_Date + End_Date + Working_Day + Total_Days
------------------------------------------------------------
| 101 | 1-Jan-18 | 5-Jan-2018 | Yes | 5 |
Table B (Expected Result):
+ LID + Start_Date + End_Date +
---------------------------------
| 101 | 1-Jan-18 | 1-Jan-2018 |
| 101 | 2-Jan-18 | 2-Jan-2018 |
| 101 | 3-Jan-18 | 3-Jan-2018 |
| 101 | 4-Jan-18 | 4-Jan-2018 |
| 101 | 5-Jan-18 | 5-Jan-2018 |
If I understand correctly, you can expand the data using a recursive CTE and then filter out the weekend days:
with cte as (
select ltd, start_date, end_date,
from a
union all
select ltd, date_add(day, 1, start_date), end_date
from cte
where start_date < end_date
)
select ltd, start_date, end_date
from cte
where datename(weekday, start_date) not in ('Saturday', 'Sunday');

Postgresql query to get count per months within one year

In MySQL
SELECT y, m, Count(users.created_date)
FROM (
SELECT y, m
FROM
(SELECT YEAR(CURDATE()) y UNION ALL SELECT YEAR(CURDATE())-1) years,
(SELECT 1 m UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4
UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8
UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL SELECT 12) months) ym
LEFT JOIN users
ON ym.y = YEAR(FROM_UNIXTIME(users.created_date))
AND ym.m = MONTH(FROM_UNIXTIME(users.created_date))
WHERE
(y=YEAR(CURDATE()) AND m<=MONTH(CURDATE()))
OR
(y<YEAR(CURDATE()) AND m>MONTH(CURDATE()))
GROUP BY y, m;
Mysql Output
+------+----+----------------------+
| y | m | Count(users.created) |
+------+----+----------------------+
| 2012 | 5 | 5595 |
| 2012 | 6 | 4431 |
| 2012 | 7 | 3299 |
| 2012 | 8 | 429 |
| 2012 | 9 | 0 |
| 2012 | 10 | 3698 |
| 2012 | 11 | 6208 |
| 2012 | 12 | 5142 |
| 2013 | 1 | 1196 |
| 2013 | 2 | 10 |
| 2013 | 3 | 0 |
| 2013 | 4 | 0 |
+------+----+----------------------+
** IN POSTGRESQL QUERY**
SELECT to_char(created_date, 'MM'),
count(id)
FROM users
WHERE created_date >
date_trunc('month', CURRENT_DATE) - INTERVAL '1 year'
GROUP BY 1
POSTGRESQL OUTPUT
postgresql output
May I know how to get postgresql output as like mysql output. Need to get results for current month within one year data.
I'm assuming what you're looking for is the rows where count is 0. If that is the case you can use generate_series and a left join on your table with data:
SELECT to_char(i, 'YY'), to_char(i, 'MM'),
count(id)
FROM generate_series(now() - INTERVAL '1 year', now(), '1 month') as i
left join users on (to_char(i, 'YY') = to_char(created_date, 'YY')
and to_char(i, 'MM') = to_char(created_date, 'MM') and login_type = 1)
GROUP BY 1,2;

Generate the rank/number if the difference between consecutive rows is less than 10 days

Need hive query that calculates the date difference for consecutive records but for the same txn type and generate same number if the difference is less than 10 else generate new number.
Input table
+--------+----------+-------------+
| Txn_id | Txn_type | Txn_date |
+--------+----------+-------------+
| 1 | T100 | 26-Aug-2015 |
| 2 | T100 | 03-Nov-2015 |
| 3 | T100 | 05-Dec-2015 |
| 4 | T100 | 08-Dec-2015 |
| 5 | T100 | 25-Jan-2016 |
| 6 | T111 | 26-Jan-2016 |
| 7 | T200 | 02-Feb-2016 |
| 8 | T200 | 07-May-2016 |
| 9 | T200 | 12-May-2016 |
| 10 | T200 | 20-May-2016 |
+--------+----------+-------------+
Expected output
+--------+----------+-------------+--------+
| Txn_id | Txn_type | Txn_date | Number |
+--------+----------+-------------+--------+
| 1 | T100 | 26-Aug-2015 | 1 |
| 2 | T100 | 03-Nov-2015 | 2 |
| 3 | T100 | 05-Dec-2015 | 3 |
| 4 | T100 | 08-Dec-2015 | 3 |
| 5 | T100 | 25-Jan-2016 | 4 |
| 6 | T111 | 26-Jan-2016 | 1 |
| 7 | T200 | 02-Feb-2016 | 1 |
| 8 | T200 | 07-May-2016 | 2 |
| 9 | T200 | 12-May-2016 | 2 |
| 10 | T200 | 20-May-2016 | 2 |
+--------+----------+-------------+--------+
Not sure if "less than 10 days" means strict or non-strict inequality, but otherwise:
with
inputs ( txn_id, txn_type, txn_date ) as (
select 1, 'T100', to_date('26-Aug-2015', 'dd-Mon-yy') from dual union all
select 2, 'T100', to_date('03-Nov-2015', 'dd-Mon-yy') from dual union all
select 3, 'T100', to_date('05-Dec-2015', 'dd-Mon-yy') from dual union all
select 4, 'T100', to_date('08-Dec-2015', 'dd-Mon-yy') from dual union all
select 5, 'T100', to_date('25-Jan-2016', 'dd-Mon-yy') from dual union all
select 6, 'T111', to_date('26-Jan-2016', 'dd-Mon-yy') from dual union all
select 7, 'T200', to_date('02-Feb-2016', 'dd-Mon-yy') from dual union all
select 8, 'T200', to_date('07-May-2016', 'dd-Mon-yy') from dual union all
select 9, 'T200', to_date('12-May-2016', 'dd-Mon-yy') from dual union all
select 10, 'T200', to_date('20-May-2016', 'dd-Mon-yy') from dual
),
prep ( txn_id, txn_type, txn_date, ct ) as (
select txn_id, txn_type, txn_date,
case when txn_date < lag(txn_date) over (partition by txn_type
order by txn_date) + 10 then 0 else 1 end
from inputs
)
select txn_id, txn_type, txn_date,
sum(ct) over (partition by txn_type order by txn_date) as number_
from prep;
I used number_ as a column name; don't use reserved Oracle words for table or column names unless your life depends on it, and not even then.
Use a common table expression to mark the rows that have a difference of more than 10 days and then count those to get the new number.
with test_data as (
SELECT 1 txn_id, 'T100' txn_type, to_date('26-AUG-2015','DD-MON-YYYY') txn_date from dual union all
SELECT 2 txn_id, 'T100', to_date('03-NOV-2015','DD-MON-YYYY') from dual union all
SELECT 3 txn_id, 'T100', to_date('05-DEC-2015','DD-MON-YYYY') from dual union all
SELECT 4 txn_id, 'T100', to_date('08-DEC-2015','DD-MON-YYYY') from dual union all
SELECT 5 txn_id, 'T100', to_date('25-JAN-2016','DD-MON-YYYY') from dual union all
SELECT 6 txn_id, 'T111', to_date('26-JAN-2016','DD-MON-YYYY') from dual union all
SELECT 7 txn_id, 'T200', to_date('02-FEB-2016','DD-MON-YYYY') from dual union all
SELECT 8 txn_id, 'T200', to_date('07-MAY-2016','DD-MON-YYYY') from dual union all
SELECT 9 txn_id, 'T200', to_date('12-MAY-2016','DD-MON-YYYY') from dual union all
SELECT 10 txn_id, 'T200', to_date('20-MAY-2016','DD-MON-YYYY') from dual),
markers as (
select td.*,
case when td.txn_date - nvl(lag(td.txn_date)
over ( partition by txn_type order by txn_id ), td.txn_date-9999) > 10
THEN 'Y' ELSE NULL end new_txn_marker from test_data td )
SELECT txn_id, txn_type,txn_date,
count(new_txn_marker) over ( partition by txn_type order by txn_id ) "NUMBER"
FROM markers;