У меня есть таблица:

ID | Name | Date
 1 | ABC  | 2015-01-01
 2 | XYZ  | 2015-01-02
 3 | ABC  | 2015-01-03
 4 | ABC  | 2015-01-04

Я хочу запросить эту таблицу таким образом, чтобы результат был следующим:

ID | Name | Date       | NextDate
 1 | ABC  | 2015-01-01 | 2015-01-03
 2 | XYZ  | 2015-01-02 | null
 3 | ABC  | 2015-01-03 | 2015-01-04
 4 | ABC  | 2015-01-04 | null

Одно из решений:

select t1.*,
  (select min(t2.Date) from TAB t2 where t2.ID > t1.ID t2.Name = t1.Name) NextDate
from TAB t1

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

6
Tamal Kanti Nath 24 Дек 2015 в 12:37

3 ответа

Лучший ответ

Поскольку SQL SERVER 2008 не поддерживает оконную функцию LEAD, мы должны моделировать ее, используя row_number и self join. Попробуй это

;WITH cte
     AS (SELECT t1.*,
                Row_number()
                  OVER(
                    partition BY Name
                    ORDER BY [Date]) AS rn
         FROM   TAB t1)
SELECT a.ID,a.Name,a.Date,b.Date as nextdate
FROM   cte a
       LEFT OUTER JOIN cte b
                    ON a.Name = b.Name
                       AND a.rn + 1 = b.rn ORDER BY a.ID
3
Nikunj Soni 24 Дек 2015 в 10:12
    SELECT ID
       ,Name
       ,Date 
       ,(CASE WHEN ID%2 !=0 THEN NextDate ELSE NULL END) AS NextDate
FROM 
(SELECT ID
        ,Name
        ,Date
        ,DATEADD(DAY,1,Date) AS NextDate
FROM YOUR_TABLE) M
0
BalajiShriram 24 Дек 2015 в 12:26

Другой способ написать это было бы.

Select a.*, c.nextDate  from table a 
outer apply (
        Select top 1 b.Date nextDate from table b 
           where b.Id > a.ID and a.Name = b.Name order by b.id 
) c
1
Abdul Rehman Sayed 24 Дек 2015 в 09:56