Динамическое сравнение дат в разных столбцах и строках в SQL - PullRequest
3 голосов
/ 19 марта 2019

У меня есть такой набор данных.

Данные

ID  Start_dt    End_dt
A   1/1/2010    12/31/2010
A   1/1/2011    12/31/2011
A   6/1/2012    12/31/2012
A   1/1/2014    12/31/2014
A   1/1/2016    10/31/2016
A   1/1/2018    12/31/2018
B   1/1/2016    2/29/2016
B   3/1/2016    10/31/2016
B   1/1/2017    7/31/2017
B   1/1/2019    12/31/9999
C   1/1/2017    12/31/2017
C   1/1/2017    12/31/2018
C   1/1/2019    12/31/9999

Мне нужно создать запрос, который просматривает строки каждого члена, сравнивает текущий Start_dt с предыдущим End_dt. Если разница составляет менее одного года, обработайте эти 2 записи как одну непрерывную регистрацию и верните объединенные значения MIN Start_dt и MAX End_dt и повторите это для всех строк для каждого члена. Если разница составляет> = 1 год, рассматривайте это как отдельную регистрацию.

Желаемый результат

ID  Start_dt    End_dt
A   1/1/2010    12/31/2012
A   1/1/2014    12/31/2014
A   1/1/2016    10/31/2016
A   1/1/2018    12/31/2018
B   1/1/2016    7/31/2017
B   1/1/2019    12/31/2019
C   1/1/2017    12/31/9999

Вот запрос создания таблицы:

if OBJECT_ID ('tempdb..#test1') is not null
drop table #test1
CREATE TABLE #test1 (
    ID varchar(10),
    Start_dt datetime,
    End_dt datetime
);

INSERT INTO #test1 VALUES ('A', '1/1/2010', '12/31/2010')
,('A', '1/1/2011', '12/31/2011')
,('A', '6/1/2012', '12/31/2012')
,('A', '1/1/2014', '12/31/2014')
,('A', '1/1/2016', '10/31/2016')
,('A', '1/1/2018', '12/31/2018')

,('B', '1/1/2016', '2/29/2016')
,('B', '3/1/2016', '10/31/2016')
,('B', '1/1/2017', '7/31/2017')
,('B', '1/1/2019', '12/31/9999')

,('C', '1/1/2017', '12/31/2017')
,('C', '1/1/2017', '12/31/2018')
,('C', '1/1/2019', '12/31/2999')

Я пытался решить эту проблему в течение нескольких дней, но пробовал самостоятельные соединения, петли, но не нашел хорошего решения. Может кто-нибудь помочь?

Спасибо!

Ответы [ 2 ]

1 голос
/ 19 марта 2019

Вы можете использовать lag() или совокупный max(), чтобы получить предыдущую дату окончания.Затем сравните его с текущей датой начала.

Если разница превышает год, начинается новая группа.У кумулятивной суммы эти новые группы начинают получать групповые идентификаторы.

А остальное агрегация:

select id, min(start_dt), max(end_dt)
from (select t1.*,
             sum(case when prev_end_dt > dateadd(year, -1, start_dt) then 0 else 1 end) over
                 (partition by id order by start_dt) as grp
      from (select t1.*,
                   max(end_dt) over (partition by id
                                      order by start_dt
                                      rows between unbounded preceding and 1 preceding
                                     ) as prev_end_dt
            from test1 t1
           ) t1
     ) t1
group by id, grp
order by id, min(start_dt);
0 голосов
/ 19 марта 2019

Вы можете попробовать этот запрос

SELECT ID, StartDate, End_dt AS EndDate
FROM (
    SELECT * 
        , LAG(End_dt) OVER(PARTITION BY ID ORDER BY ID, Start_dt, End_dt) AS PrevEnd
        , DATEDIFF(DAY, LAG(End_dt) OVER(PARTITION BY ID ORDER BY ID, Start_dt, End_dt), Start_dt) AS DaysBreak
        , (
            CASE
                WHEN DATEDIFF(DAY, LAG(End_dt) OVER(PARTITION BY ID ORDER BY ID, Start_dt, End_dt), Start_dt) > 365 THEN Start_dt
                WHEN LAG(End_dt) OVER(PARTITION BY ID ORDER BY ID, Start_dt, End_dt) IS NULL THEN Start_dt
                ELSE NULL
            END
        ) AS StartDate
    FROM #test1
) a
WHERE StartDate IS NOT NULL
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...