Требуется четыре шага, чтобы получить результат, представленный тремя подзапросами и одним основным запросом:
1) увеличить END_DATE до максимума до настоящего времени
Этотребуется, поскольку ваш END_DATE
не упорядочен, например, первая запись пересекается с третьей записью, но вторая запись не пересекается с третьей.
ID_USER START_DATE END_DATE
---------- ------------------- -------------------
1 01.01.2018 08:00:00 01.01.2018 08:50:00
1 01.01.2018 08:15:00 01.01.2018 08:50:00
1 01.01.2018 08:45:00 01.01.2018 09:55:00
1 01.01.2018 15:45:00 01.01.2018 17:00:00
2 01.01.2018 08:45:00 01.01.2018 09:50:00
2 01.01.2018 09:15:00 01.01.2018 10:00:00
2) Определитьновая группа для каждого неперекрывающегося фрагмента
Технически для первой записи (для USER_ID) и для каждой записи, которая не перекрывается с предшественником ist - назначьте новый group_id (GRP
)
ID_USER START_DATE END_DATE GRP
---------- ------------------- ------------------- ----------
1 01.01.2018 08:00:00 01.01.2018 08:50:00 1
1 01.01.2018 08:15:00 01.01.2018 08:50:00
1 01.01.2018 08:45:00 01.01.2018 09:55:00
1 01.01.2018 15:45:00 01.01.2018 17:00:00 4
2 01.01.2018 08:45:00 01.01.2018 09:50:00 1
2 01.01.2018 09:15:00 01.01.2018 10:00:00
3) Заполнить группы
Заполнить NULL
с последним идентификатором группы, назначенным для включения GROUP BY.
ID_USER START_DATE END_DATE GRP2
---------- ------------------- ------------------- ----------
1 01.01.2018 08:00:00 01.01.2018 08:50:00 1
1 01.01.2018 08:15:00 01.01.2018 08:50:00 1
1 01.01.2018 08:45:00 01.01.2018 09:55:00 1
1 01.01.2018 15:45:00 01.01.2018 17:00:00 4
2 01.01.2018 08:45:00 01.01.2018 09:50:00 1
2 01.01.2018 09:15:00 01.01.2018 10:00:00 1
4) GROUP BY
Остальное просто, даты в группе минимальные и максимальные.Вы группируете по kay (ID_USER
) и teh GRP
.
ID_USER START_DATE END_DATE
---------- ------------------- -------------------
1 01.01.2018 08:00:00 01.01.2018 09:55:00
1 01.01.2018 15:45:00 01.01.2018 17:00:00
2 01.01.2018 08:45:00 01.01.2018 10:00:00
Запрос
with myt1 as (
select ID_USER, START_DATE,
max(END_DATE) over (partition by ID_USER order by START_DATE) END_DATE
from my_table),
myt2 as (
select ID_USER,START_DATE, END_DATE,
case when (nvl(lag(END_DATE) over (partition by ID_USER order by START_DATE),START_DATE-1) < START_DATE ) then
row_number() over (partition by ID_USER order by START_DATE) end grp
from myt1
),
myt3 as (
select ID_USER,START_DATE, END_DATE,
last_value(grp ignore nulls) over (partition by ID_USER order by START_DATE) as grp2
from myt2
),
select
ID_USER,
min(START_DATE) START_DATE,
max(END_DATE) END_DATE
from myt3
group by ID_USER, GRP2
order by 1,2;
Данные
create table my_table as
select 1 ID_USER, to_date('01/01/2018 08:00:00','dd/mm/yyyy hh24:mi:ss') START_DATE, to_date('01/01/2018 08:50:00','dd/mm/yyyy hh24:mi:ss') END_DATE from dual union all
select 1 ID_USER, to_date('01/01/2018 08:15:00','dd/mm/yyyy hh24:mi:ss') START_DATE, to_date('01/01/2018 08:20:00','dd/mm/yyyy hh24:mi:ss') END_DATE from dual union all
select 1 ID_USER, to_date('01/01/2018 08:45:00','dd/mm/yyyy hh24:mi:ss') START_DATE, to_date('01/01/2018 09:55:00','dd/mm/yyyy hh24:mi:ss') END_DATE from dual union all
select 1 ID_USER, to_date('01/01/2018 15:45:00','dd/mm/yyyy hh24:mi:ss') START_DATE, to_date('01/01/2018 17:00:00','dd/mm/yyyy hh24:mi:ss') END_DATE from dual union all
select 2 ID_USER, to_date('01/01/2018 08:45:00','dd/mm/yyyy hh24:mi:ss') START_DATE, to_date('01/01/2018 09:50:00','dd/mm/yyyy hh24:mi:ss') END_DATE from dual union all
select 2 ID_USER, to_date('01/01/2018 09:15:00','dd/mm/yyyy hh24:mi:ss') START_DATE, to_date('01/01/2018 10:00:00','dd/mm/yyyy hh24:mi:ss') END_DATE from dual;