SQL Server を介してテーブルに挿入されたばかりの日付キーにこの問題があります。これらは、以下に示す方法で繰り返し入力されます。
- 20130501
- 20130502
- 20130503
- ...
私は現在、日付の1つがスキップされた行を見つけようとしています。
- 20130504
- 20130506
- 20130507
私はまだ SQL Server の初心者であり、CURSOR を見てきましたが、これをクエリする方法を理解するのに苦労しています。どんな助けでも大歓迎です。ありがとう。
SQL Server を介してテーブルに挿入されたばかりの日付キーにこの問題があります。これらは、以下に示す方法で繰り返し入力されます。
私は現在、日付の1つがスキップされた行を見つけようとしています。
私はまだ SQL Server の初心者であり、CURSOR を見てきましたが、これをクエリする方法を理解するのに苦労しています。どんな助けでも大歓迎です。ありがとう。
Itzik Ben-Gan の考え方のいくつかのトリックを使用します。ギャップを見つける最も簡単な方法は、集計表を使用することです。テーブル変数に小さなものを作成する方法は次のとおりですが、この種の作業には非常に便利なので、実証済みの Numbers テーブルを作成することをお勧めします。これを行う方法については、ここでたくさんの例を見つけることができます。
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 のために、指定したキーを datetime に変更します。
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
SELECT *
FROM table
WHERE date - 1 NOT IN (SELECT date FROM table)
おそらく非常に効率的ではありませんが、うまくいくはずです。