SQL, чтобы найти дату начала и окончания для идентификатора - PullRequest
0 голосов
/ 21 октября 2019

У меня есть таблица со столбцами ID, start_date и end_date.

Таблица:

ID    start_date    end_date
1     01/01/2017    01/01/2018
1     01/01/2018    01/01/2019
1     01/01/2019    01/01/2020
2     01/01/2016    01/01/2017
2     01/01/2017    01/01/2018
2     01/01/2019    01/01/2020

Я хочу написать запрос для получения следующего вывода:

Вывод:

ID    start_date    end_date
1     01/01/2017    01/01/2020
2     01/01/2016    01/01/2018
2     01/01/2019    01/01/2020

Ответы [ 3 ]

0 голосов
/ 21 октября 2019

Вы можете сделать кумулятивную сумму, чтобы решить эту вариацию проблемы пробелов и островов:

select 
    id,
    min(start_date) start_date,
    max(end_date) end_date
from (
    select 
        t.*,
        sum(case when start_date = lag_end_date then 0 else 1 end) 
            over(partition by id order by start_date) grp
    from (
        select 
            t.*,
            lag(end_date) over(partition by id order by start_date) lag_end_date
        from mytable t
    ) t
) t
group by id, grp
order by id, grp

Демонстрация на DB Fiddle :

ID | START_DATE | END_DATE  
-: | :--------- | :---------
 1 | 01/01/2017 | 01/01/2020
 2 | 01/01/2016 | 01/01/2018
 2 | 01/01/2019 | 01/01/2020
0 голосов
/ 21 октября 2019
     Select id, Min(startdate), Max(case 
          when 
           lag(enddate) 
         over
    (partition by id order by id) =startdate
       then 
       Enddate end) from table group by
       id;
0 голосов
/ 21 октября 2019

Это форма пробелов и островков.

В этом случае я рекомендую использовать кумулятивный максимум, чтобы увидеть, есть ли какие-либо совпадения с предыдущими строками, и использовать его, чтобы определить, где начинается «остров». ,Затем используйте накопленную сумму, чтобы определить острова и совокупность:

select id, min(start_date), max(end_date
from (select t.*,
             sum(case when prev_end_date >= start_date then 0 else 1 end) over (partition by id order by start_date) as grp
      from (select t.*,
                   lag(end_date) over (partition by id
                                       order by start_date
                                       rows between unbounded preceding and 1 preceding
                                      ) as prev_end_date
            from t
           ) t
      ) t
group by id, grp;
...