SQL - 检查日期是否按正确顺序

时间:2015-06-01 09:57:05

标签: sql sql-server-2008-r2

我有一张这样的表:

id    start      end
1     1-1-2015   29-1-2015
2     30-1-2015  28-2-2015
3     1-3-2015   30-3-2015
.... 

现在我需要sql查询,该查询将检查end date行和下一行start dat e之间是否遗漏了任何日期。

E.g。如果end date29-1-2015,那么下一行的start date应该始终是该30-1-2015的下一个日期。 如果错过了任何日期,则应该返回错误。

2 个答案:

答案 0 :(得分:2)

您可以使用APPLY获取下一条记录(假设您使用ID的顺序定义下一条记录),然后过滤掉下一条记录的开头与当前结尾不匹配的记录记录:

SELECT  *
FROM    YourTable AS T1
        CROSS APPLY
        (   SELECT  TOP 1 T2.[Start]
            FROM    YourTable AS T2
            WHERE   T2.ID > T1.ID
            ORDER BY T2.ID
        ) AS NextStart
WHERE   NextStart.[Start] != DATEADD(DAY, 1, T1.[End]);

如果您的ID列没有间隙,您可以使用连接:

SELECT  *
FROM    YourTable AS T1
        INNER JOIN YourTable AS NextStart
            ON T2.ID = T.ID + 1
WHERE   NextStart.[Start] != DATEADD(DAY, 1, T.[End]);

如果一个句点的开头应该始终是前一个句点结束后的第二天,那么为什么不为此存储单个值。例如您需要存储的只有:

id    start     
1     2015-01-01  
2     2015-01-30 
3     2015-03-01 

现在,您可以通过查找下一个开始日期来定义结束日期:

SELECT  t.id,
        t.start,
        [end] = DATEADD(DAY, -1, e.start)
FROM    dbo.YourTable AS t
        OUTER APPLY
        (   SELECT  TOP 1 start
            FROM    dbo.YourTable AS T2
            WHERE   t2.ID > t.ID
            ORDER BY ID
        ) AS e;

如果您需要定期开始和结束,则可以将其设为视图,并确保您没有任何遗漏期。

答案 1 :(得分:0)

尝试使用简单的连接:

DECLARE @t TABLE ( id INT, s DATE, e DATE )

INSERT  INTO @t
VALUES  ( 1, '20150101', '20150129' ),
        ( 2, '20150130', '20150228' ),
        ( 3, '20150301', '20150330' ),
        ( 4, '20150501', '20150630' );

WITH    cte
          AS ( SELECT   ROW_NUMBER() OVER ( ORDER BY id ) AS id ,
                        s ,
                        e
               FROM     @t
             )
    SELECT  c2.id ,
            c1.id
    FROM    cte c1
            JOIN cte c2 ON c2.id + 1 = c1.id
    WHERE   DATEADD(d, 1, c2.e) <> c1.s

输出:

id  id
3   4

首先,您要使用连续数字对行进行编号。然后,您将加入下一行的行,并检查是否在prev行值中添加1天为您提供下一行值。

如果您已经连续CTE,只需删除id