我有这个问题,日期键刚刚通过 SQL Server 插入到表中。它们以如下所示的方式迭代填充:
- 20130501
- 20130502
- 20130503
- ...
我目前正在尝试查找跳过其中一个日期的任何行,即:
- 20130504
- 20130506
- 20130507
我仍然是 SQL Server 的新手,我已经看过 CURSOR,但我在理解如何进行查询时遇到了一些麻烦。任何帮助,将不胜感激。谢谢。
我有这个问题,日期键刚刚通过 SQL Server 插入到表中。它们以如下所示的方式迭代填充:
我目前正在尝试查找跳过其中一个日期的任何行,即:
我仍然是 SQL Server 的新手,我已经看过 CURSOR,但我在理解如何进行查询时遇到了一些麻烦。任何帮助,将不胜感激。谢谢。
SELECT *
FROM table
WHERE date - 1 NOT IN (SELECT date FROM table)
它可能不是超级有效,但它应该可以工作。
使用来自 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