2015-12-24 2 views
6

У меня есть таблица:Как найти следующее значение в таблице на основе определенных критериев

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 

One Раствор равен:

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

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

+2

Любой шанс модернизировать ваш SQL Server 2008 к 2012 или новее? Функция ['lead'] (https://msdn.microsoft.com/en-us/library/hh213125.aspx), похоже, точно соответствует вашему счету. – Mureinik

ответ

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 
1

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

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 
0
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