我有这个问题,其中日期键只是通过SQL Server插入表中。它们以下面显示的方式迭代填充:
我目前正试图找到其中一个日期被跳过的任何行,即:
我仍然是SQL Server的新手,我看过CURSOR,但是我在理解如何查询这个问题时遇到了一些麻烦。任何帮助,将不胜感激。感谢。
答案 0 :(得分:0)
SELECT *
FROM table
WHERE date - 1 NOT IN (SELECT date FROM table)
这可能不是超级有效但它应该有用。
答案 1 :(得分:0)
使用Itzik Ben-Gan学派的一些技巧。找到差距的最简单方法是使用计数表。这是一种在表变量中创建一个小表的方法,但我建议创建一个经过证实的Numbers表,因为它们对于这种事情非常方便。您可以找到一些关于如何执行此操作的示例here。
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:将您提供的密钥更改为日期时间以便于比较和dateadd。
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