2017-02-14 15 views
4

Выборочные данные здесь:
http://rextester.com/VNGMF66717Lead функция окна с дубликата даты

У меня есть следующие данные:

ID Year Date  
1111 2016 2016-02-28 
1111 2016 2016-02-28 
1111 2016 2016-03-31 
1111 2016 2016-03-31 
1111 2016 2016-03-31 
1111 2016 2016-04-02 
1111 2016 2016-05-31 
1111 2016 2016-08-01 
1111 2016 2016-12-11 
1111 2017 2017-01-02 
1111 2017 2017-01-02 
1111 2017 2017-02-04 
1111 2017 2017-02-04 
1111 2017 2017-07-08 
2222 2016 2016-02-11 
2222 2016 2016-02-11 
2222 2016 2016-03-28 
2222 2016 2016-03-28 
2222 2016 2016-03-28 
2222 2016 2016-07-22 
2222 2016 2016-12-31 
2222 2017 2017-02-01 
2222 2017 2017-02-14 

Я хочу, чтобы добавить столбец NextDate (который сбрасывает в пределах каждого ID и год), используя ведущую функцию окна непосредственно в инструкции SELECT, вместо самостоятельного присоединения с использованием функции окна RANK, как я сделал в приведенном примере.

NextDate колонка должна быть точно так же как это

ID Year Date  NextDate 
1111 2016 2016-02-28 2016-03-31 
1111 2016 2016-02-28 2016-03-31 
1111 2016 2016-03-31 2016-04-02 
1111 2016 2016-03-31 2016-04-02 
1111 2016 2016-03-31 2016-04-02 
1111 2016 2016-04-02 2016-05-31 
1111 2016 2016-05-31 2016-08-01 
1111 2016 2016-08-01 2016-12-11 
1111 2016 2016-12-11 NULL 
1111 2017 2017-01-02 2017-02-04 
1111 2017 2017-01-02 2017-02-04 
1111 2017 2017-02-04 2017-07-08 
1111 2017 2017-02-04 2017-07-08 
1111 2017 2017-07-08 NULL 
2222 2016 2016-02-11 2016-03-28 
2222 2016 2016-02-11 2016-03-28 
2222 2016 2016-03-28 2016-07-22 
2222 2016 2016-03-28 2016-07-22 
2222 2016 2016-03-28 2016-07-22 
2222 2016 2016-07-22 2016-12-31 
2222 2016 2016-12-31 NULL 
2222 2017 2017-02-01 2017-02-14 
2222 2017 2017-02-14 NULL 

Кто знает, как сделать это правильно?

+0

Что вы пытаетесь? – Lali

+0

, пожалуйста, добавьте свой код рекстестера в сообщение, чтобы не полагаться на ссылку. – Tanner

+2

@Lali: В ссылке пользователь предоставил образцы данных вместе с тем, что он пробовал – TheGameiswar

ответ

3

Это не может быть именно то, что вы имели в виду , но используя две функции окна с вложенным select: MAX (LEAD), вы получите желаемый результат.

select 
    id, yr, dt 
    ,MAX(nx_dt) OVER (PARTITION BY id, dt) nxt_dt 
FROM 
    (
     select 
      * 
      , LEAD(dt) OVER (PARTITION BY id, yr ORDER BY id, yr, dt) nx_dt 
     from 
     #testtable 
    ) sub 

/* 
drop table #testtable 

create table #testtable 
(
    id int, yr int, dt date 
) 
insert into #testtable 
(
    id, yr, dt 
) 
SELECT 1111,2016,'2016-02-28' union all 
SELECT 1111,2016,'2016-02-28' union all 
SELECT 1111,2016,'2016-03-31' union all 
SELECT 1111,2016,'2016-03-31' union all 
SELECT 1111,2016,'2016-03-31' union all 
SELECT 1111,2016,'2016-04-02' union all 
SELECT 1111,2016,'2016-05-31' union all 
SELECT 1111,2016,'2016-08-01' union all 
SELECT 1111,2016,'2016-12-11' union all 
SELECT 1111,2017,'2017-01-02' union all 
SELECT 1111,2017,'2017-01-02' union all 
SELECT 1111,2017,'2017-02-04' union all 
SELECT 1111,2017,'2017-02-04' union all 
SELECT 1111,2017,'2017-07-08' union all 
SELECT 2222,2016,'2016-02-11' union all 
SELECT 2222,2016,'2016-02-11' union all 
SELECT 2222,2016,'2016-03-28' union all 
SELECT 2222,2016,'2016-03-28' union all 
SELECT 2222,2016,'2016-03-28' union all 
SELECT 2222,2016,'2016-07-22' union all 
SELECT 2222,2016,'2016-12-31' union all 
SELECT 2222,2017,'2017-02-01' union all 
SELECT 2222,2017,'2017-02-14' 
*/ 
+0

Любимый ... –

3

Я это вам нужно сделать это с outer apply или подзапроса:

select cte.*, next_cte.date 
from cte outer apply 
    (select top 1 cte2.* 
     from cte cte2 
     where cte2.id = cte.id and cte2.year = cte.year and 
      cte2.date > cte.date 
     order by cte2.date desc 
    ) next_cte; 

Другой альтернативой является сделать lead() на различных значениях:

select cte.*, cte_next.next_date 
from cte join 
    (select id, year, date, 
      lead(date) over (partition by id, year order by date) as next_date 
     from cte 
     group by id, year, date 
    ) cte_next 
    ON cte.id = cte_next.id and cte.year = cte_next.year and cte.date = cte_next.date; 
+0

Невозможно (или, возможно, даже невозможно) избежать того, чтобы сделать запрос/внешний запрос, чтобы получить желаемый результат? –

+0

@EmilVissing. , , Я так не думаю, но, возможно, кто-то еще придумает решение. –

+1

join ... on ... –

0

Другой подход будет использовать коррелированный подзапрос, который получает следующую дату в течение года, если LEAD возвращает ту же дату, как текущая дата для идентификатора.

SELECT 
     [ID] 
    ,[Year] 
    ,[Date] 
    ,CASE WHEN LEAD([Date]) OVER(PARTITION BY [ID],[Year] ORDER BY [Date]) = [Date] 
     THEN (SELECT MIN([Date]) FROM CTE WHERE [Date]>c.[Date] and [ID]=c.[ID] and [Year]=c.[Year]) 
     ELSE LEAD([Date]) OVER(PARTITION BY [ID],[Year] ORDER BY [Date]) END AS [NextDate] 
FROM CTE C