注:最初にこの回答を書いたとき、列の1つにインデックスを付けると、他の回答よりもパフォーマンスの高いクエリを作成できると言いました(そしてDan Fullerのことを述べました)。しかし、100%正しく考えていたわけではありません。実際には、計算列またはインデックス付き (マテリアライズド) ビューがなければ、比較対象の 2 つの日付列が同じテーブルのものであるため、完全なテーブル スキャンが必要になります。
以下の情報にはまだ価値があると思います。つまり、1) 異なるテーブルの列を比較する場合など、適切な状況でパフォーマンスが向上する可能性、および 2) SQL 開発者にベスト プラクティスに従って再形成する習慣を促進することです。彼らの考えを正しい方向に。
条件を検索可能にする
私が言及しているベスト プラクティスは、次のように、1 つの列を比較演算子の片側だけに移動することです。
SELECT InitialSave = DateDiff(second, T.BegTime, T.EndTime)
FROM dbo.MyTable T
WHERE T.EndTime <= T.BegTime + '00:00:10'
前述したように、これは単一のテーブルでのスキャンを回避するものではありませんが、このような状況では大きな違いが生じる可能性があります。
SELECT InitialSave = DateDiff(second, T.BegTime, T.EndTime)
FROM
dbo.BeginTime B
INNER JOIN dbo.EndTime E
ON B.BeginTime <= E.EndTime
AND B.BeginTime + '00:00:10' > E.EndTime
EndTime
両方の状態で、比較の片側に一人でいます。BeginTime
テーブルの行がはるかに少なく、EndTime
テーブルの列にインデックスがあると仮定するとEndTime
、これは を使用した何よりもはるかに優れたパフォーマンスを発揮しDateDiff(second, B.BeginTime, E.EndTime)
ます。これは、有効な「検索引数」があることを意味します。つまり、エンジンがテーブルをスキャンするときに、テーブルをシークBeginTime
できます。演算子の片側にある列を慎重に選択する必要があります。代数を実行して切り替えることで、単独で配置することで実験する価値があります。EndTime
BeginTime
AND B.BeginTime > E.EndTime - '00:00:10'
DateDiff の精度
は経過DateDiff
時間を返すのではなく、通過した境界の数をカウントすることも指摘しておく必要があります。using secondsの呼び出しで が返された場合、これは経過時間または!を意味する可能性があります。これは基本的に、時間単位 +-1 の精度です。+- 1/2 時間単位の精度を高めるには、次のクエリと比較する必要があります。DateDiff
1
3 ms
1997 ms
0
EndTime - BegTime
SELECT DateDiff(second, 0, EndTime - BegTime) AS InitialSave
FROM MyTable
WHERE EndTime <= BegTime + '00:00:10'
これにより、丸め誤差の最大値が合計 2 秒ではなく 1 秒になりました (事実上、floor() 操作)。datetime
データ型を減算することしかできないことに注意してください。date
または値を減算するtime
には、変換するdatetime
か、他の方法を使用してより良い精度を取得する必要があります(大量のDateAdd
.DateDiff
単位と分割)。
この原則は、時間、日、月などの大きな単位を数える場合に特に重要です。DateDiff
は62 日離れている1 month
可能性があります (2013 年 7 月 1 日から 2013 年 8 月 31 日までと考えてください)。