SQL2008 を使用して、日付が特定のターゲット日付に最も近い行を見つけるための効率的なクエリを見つけようとしています。
私のテーブルには日付が最初の列であるカバリング インデックスが既にあるため、私が気にしなかった明らかな非効率的な解決策 (たとえば、ABS および DATEDIFFを使用したテーブル スキャン) があります。どの行が最も近いかを正確に把握する前に、そのインデックスを使用して結果を絞り込むことができます。
理論的には、1 回のインデックス ルックアップと、そのインデックスからの 2 行のデータの連続プルを使用して、クエリを満たすことができるはずです。
しかし、これまでのところ、これよりも最適なソリューションを見つけることができませんでした:
DECLARE @target DATETIME = '01/02/2011'
SELECT TOP 1 Val, Measured
FROM (
SELECT TOP 1 Val, Measured
FROM tbl
WHERE Measured <= @Target
ORDER BY Measured desc
UNION ALL
SELECT TOP 1 Val, Measured
FROM tbl
WHERE Measured >= @Target
ORDER BY Measured asc
) x
ORDER BY ABS (DATEDIFF (second, Measured, @Target))
これは高速ですが (以下のテスト スキーマでは 4 回の論理読み取り、実際のテーブルでは 9 回の論理読み取り)、それでも 2 回のスキャン カウント ソリューションです。このインデックスに一度だけヒットするより効率的なソリューションはありますか?
または、2 番目のインデックス シークが最初のシークによってアクセスされるキャッシュされたページをプルするため、私の既存のソリューションは「十分」ですか?
スキーマといくつかのサンプル データを次に示します。どちらも実際のスキーマから単純化されていますが、結果のクエリ プランはより複雑なテーブルと同じになります。
CREATE TABLE tbl
(
ID int IDENTITY(1,1) PRIMARY KEY CLUSTERED NOT NULL,
Measured DATETIME NOT NULL,
Val int NOT NULL
);
CREATE NONCLUSTERED INDEX IX_tbl ON tbl (Measured) INCLUDE (Val)
INSERT tbl VALUES ('2011-01-01 12:34',6);
INSERT tbl VALUES ('2011-01-01 23:34',6);
INSERT tbl VALUES ('2011-01-03 09:03',12);
INSERT tbl VALUES ('2011-02-01 09:24',18);
INSERT tbl VALUES ('2011-02-08 07:12',7);
INSERT tbl VALUES ('2011-03-01 12:34',6);
INSERT tbl VALUES ('2011-04-03 09:03',12);
INSERT tbl VALUES ('2011-05-01 09:24',18);
INSERT tbl VALUES ('2011-06-08 07:12',7);
-- insert another few million rows here to compare to my real-world table