0

我有这个问题,日期键刚刚通过 SQL Server 插入到表中。它们以如下所示的方式迭代填充:

  • 20130501
  • 20130502
  • 20130503
  • ...

我目前正在尝试查找跳过其中一个日期的任何行,即:

  • 20130504
  • 20130506
  • 20130507

我仍然是 SQL Server 的新手,我已经看过 CURSOR,但我在理解如何进行查询时遇到了一些麻烦。任何帮助,将不胜感激。谢谢。

4

2 回答 2

0
SELECT *
FROM table
WHERE date - 1 NOT IN (SELECT date FROM table)

它可能不是超级有效,但它应该可以工作。

于 2013-05-10T20:43:11.283 回答
0

使用来自 Itzik Ben-Gan 学派的一些技巧。找出差距的最简单方法是使用计数表。这是一种在表变量中创建一个小变量的方法,但我建议创建一个经过证实的数字表,因为它们对于这种事情真的很方便。您可以在此处找到有关如何执行此操作的大量示例。

首先创建一个数字表

DECLARE @Numbers TABLE ( [Number] INT );

    INSERT  INTO @Numbers
    (
      Number
    )
    SELECT TOP 1000
            ROW_NUMBER() OVER (ORDER BY [s1].[object_id]) AS Number
    FROM    sys.objects s1
    CROSS JOIN sys.objects s2

接下来我需要创建一个临时表来重新创建您的示例

DECLARE @ExampleDates TABLE ( [RecordDateKey] INT );

INSERT  INTO @ExampleDates
    ( [RecordDateKey] )
VALUES  ( 20130501 ),
        ( 20130502 ),
        ( 20130503 ),
        ( 20130504 ),
        ( 20130506 ),
        ( 20130507 ),
        ( 20130508 ),
        ( 20130511 );

此语法仅适用于 2008-r2 及更高版本,但由于我只是在暂存数据,所以这并不是什么大问题。只需将此注释留给其他测试此示例的人。

最后我们需要做一些转换工作。

对于较大的集合,证实这些数据可能是有益的,但对于这个小例子,一个 cte 就足够了。

WITH    date_convert
      AS (
           SELECT   [RecordDateKey]
                  , CONVERT(DATETIME, CAST([RecordDateKey] AS VARCHAR(50)), 112) [RecordDate]
           FROM     @ExampleDates ed
         ) ,
    date_range
      AS (
           SELECT   DATEDIFF(DAY, MIN([RecordDate]), MAX([RecordDate])) [Range]
                  , MIN([RecordDate]) [StartDate]
           FROM     [date_convert]
         ) ,
    all_dates
      AS (
           SELECT   CONVERT(INT, CONVERT(VARCHAR(8), DATEADD(DAY, num.[Number], [StartDate]), 112)) AS [RecordDateKey]
                  , DATEADD(DAY, num.[Number], [StartDate]) [RecordDate]
           FROM     @Numbers num
           CROSS JOIN [date_range] dr
           WHERE    num.[Number] <= dr.[Range]
         )
 SELECT [RecordDateKey]
      , [RecordDate]
 FROM   all_dates ad
 WHERE  NOT EXISTS ( SELECT 1
                     FROM   [date_convert] dc
                     WHERE  ad.[RecordDate] = dc.RecordDate )
  • date_convert:将您提供的键更改为日期时间,以便于比较和添加日期。

  • date_range:查找日期范围,以及范围开始的位置。

  • all_dates:查找应该存在于您的范围内的所有日期。

  • 最后的选择在数据中查找不在生成集中的记录。

使用此代码,这是我的输出。无论间隙大小如何,这都应该找到间隙。这似乎是当前接受的答案的问题。

RecordDateKey   RecordDate
-------------   ----------
20130505        2013-05-05 00:00:00.000
20130509        2013-05-09 00:00:00.000
20130510        2013-05-10 00:00:00.000
于 2013-05-11T12:41:50.390 回答