日付間隔のある SQL WHERE 句 - どの方法が最適ですか?
環境
データ保護法により、特定のデータは設定された時間にシステムから削除する必要があります。ほとんどの場合、7 年です。
クライアントサイトでこれを調査したところ、送信されたクエリを確認したところ、奇妙な結果が得られていました。
SQL
SELECT *FROM AccountsWHERE DATEDIFF(YEAR,ClosedDate,GETDATE())>=7
テスト テーブルを作成する
これで正しいボリュームのように見えましたが、さらに調べてみると、7 年前に静的な日付を作成した場合よりも多くのアカウントがあったので、なぜそれを行ったのでしょうか?
それを調査するために、次のコードを作成しました。
SQL
DECLARE @Records TABLE (RecordID INT,RecordClosed DATETIME)DECLARE @InsRecID INT = 1DECLARE @InsRecDate DATE=DATEADD(YEAR,-8,GETDATE())WHILE @InsRecDate INSERT INTO @Records SELECT @InsRecID,@InsRecDate SET @InsRecID = @InsRecID+1 SET @InsRecDate=DATEADD(DAY,1,@InsRecDate)ENDDECLARE @DateFrom DATE=DATEADD(YEAR,-7,GETDATE())SELECT MAX(RecordClosed) FROM @RecordsSELECT MAX(RecordClosed) FROM @Records WHERE DATEDIFF(YEAR,RecordClosed,getdate())>=7SELECT MAX(RecordClosed) FROM @Records WHERE RecordClosed<@DateFromSELECT MAX(RecordClosed) FROM @Records WHERE RecordClosed<=@DateFromSELECT MAX(RecordClosed) FROM @Records WHERE DATEDIFF(DAY,RecordClosed,getdate())/365.25>7
テスト
Results
2007-03-21 00:00:00.000
2006-12-31 00:00:00.000
2006-03-20 00:00:00.000
2006-03-21 00:00:00.000
2006-03-21 00:00:00.000
何が正しいですか?
最初のレコードは一時テーブルの最大の日付なので、問題ありません。
2 番目のレコードは、2006 年末までのすべてのアカウントをピックアップしています。削除されたデータが多すぎるため、これは潜在的な問題であった可能性があります。年のDATEDIFFは、年が7年前であることを純粋にチェックしています。
3 番目と 4 番目のレコードは、7 年前の日を in または out として含めるかどうかに応じて、必要なレコードです。5 番目のレコードは、実行時には正確ですが、うるう年の計算を使用しており、正確さを期すために、具体的に言わなければならない場合は信頼できません。
Speed difference
While checking the records, I ran it on the system checking 2,500,000 records for 3 and 5 above.
Statement 5 returned our result in 6 seconds, Statement 3 in only 3 seconds, so not only were we now sure that we were accurate, but we were also processing the records quicker.
Try to use a proper date when querying dates, hope this helps someone scratching their head.