非常に大きなテーブルにSQL datetime
フィールドがあります。インデックスが作成されており、クエリが必要です。
問題は、SQLが常に時刻コンポーネントを格納することです(常に真夜中であっても)が、検索は時刻ではなく日に対して行われます。
declare @dateVar datetime = '2013-03-11;
select t.[DateColumn]
from MyTable t
where t.[DateColumn] = dateVar;
t.[DateColumn]
には常に時間コンポーネントが含まれるため、何も返されません。
私の質問は、これを回る最善の方法は何ですか?
オプションには主に2つのグループがあるようです。
dateadd
を使用して2番目の変数を作成し、between ... and
または>= ... and ... <=
を使用します。
t.[DateColumn]
を日付のみのコンポーネントに変換します-これにより、すべてのインデックスが無視されます。
これらはどちらも非常に厄介に見えます-範囲の比較やテーブルのスキャンは本当にしたくありません。
もっと良い方法はありますか?
これらのオプションのいずれかが一貫して最適な方法である場合、どのように、なぜですか?
いずれの場合でも、DATE
に変換するか、無制限の日付範囲を使用すると、最高のパフォーマンスが得られます。参考までに、インデックスを使用して日付に変換するのが最高のパフォーマンスです。記事のさまざまなテクニックをさらにテスト: datetimeから時間をトリムする最も効率的な方法は何ですか? アーロンバートランド投稿
その記事から:
_DECLARE @dateVar datetime = '19700204';
-- Quickest when there is an index on t.[DateColumn],
-- because CONVERT can still use the index.
SELECT t.[DateColumn]
FROM MyTable t
WHERE = CONVERT(DATE, t.[DateColumn]) = CONVERT(DATE, @dateVar);
-- Quicker when there is no index on t.[DateColumn]
DECLARE @dateEnd datetime = DATEADD(DAY, 1, @dateVar);
SELECT t.[DateColumn]
FROM MyTable t
WHERE t.[DateColumn] >= @dateVar AND
t.[DateColumn] < @dateEnd;
_
また、その記事から:BETWEEN
、DATEDIFF
、またはCONVERT(CHAR(8)...
の使用はすべて低速です。
以下に例を示します。
OrderDateというDateTimeフィールドを持つOrderテーブルがあります。注文日が2006年1月1日であるすべての注文を取得したい。次の方法があります:
1) WHERE DateDiff(dd, OrderDate, '01/01/2006') = 0
2) WHERE Convert(varchar(20), OrderDate, 101) = '01/01/2006'
3) WHERE Year(OrderDate) = 2006 AND Month(OrderDate) = 1 and Day(OrderDate)=1
4) WHERE OrderDate LIKE '01/01/2006%'
5) WHERE OrderDate >= '01/01/2006' AND OrderDate < '01/02/2006'
見つかった ここ
日付がfromdateとtoDateの間にあるときにアイテムを取得します。
ここで、convert(date、fromdate、103)<= '2016-07-26'およびconvert(date、toDate、103)> = '2016-07-26'
時刻なしで日付のみを含む計算列を追加できます。 2つのオプションの間では、BETWEEN
演算子を使用します。これは、それが "クリーン"であり、インデックスをより有効に使用する必要があるためです。実行計画を比較すると、BETWEEN
の方が速いことがわかります。ただし、実際のテストでは同じことを実行しました。