@マット@ケイン
ケインは、不等式のために間違った列を選んだことを除いて、うまくいきました。いくつか修正しました。誰かが、相関するサブクエリとCROSS APPLYメソッドからドアを吹き飛ばす「風変わりな更新」以外のより高速なメソッドを思い付くことができれば、私は驚きます。
これは、パフォーマンステストの目的でスティックを振ることができるよりも多くのテストデータを構築するためのコードです。
--===== Conditionallly drop the test table to make reruns in SSMS easier
IF OBJECT_ID('tempdb..#Test','U') IS NOT NULL
DROP TABLE #Test
;
--===== Create and populate the test table on-the-fly
-- using a "Pseudo Cursor" which is many times
-- faster than a WHILE loop.
SELECT TOP 100000
FK = ABS(CHECKSUM(NEWID()))%100+100, -- 100 thru 199
Priority = ABS(CHECKSUM(NEWID()))%100+1, -- 1 thru 100
PriorityUpdateDateTime = DATEADD(dd,
ABS(CHECKSUM(NEWID()))%DATEDIFF(dd,'2000','2010')
,'2000') --20000101 thru 20091231
INTO #Test
FROM sys.all_columns ac1 --has more than 4000 rows even on a new system
CROSS JOIN sys.all_columns ac2
;
--===== Create a clustered index to improve performance by about 10 times in this case
CREATE INDEX IX_#Test ON #Test (FK,PriorityUpdateDateTime)
;
これがKaneのコードの2つの異なる表現です。詳細はコードにあります。どちらもほぼ同じ時間で同じ結果を返します。
--===== Kane's correlated subquery works just fine here once we
-- flip it around and use a different column name in the
-- inequality part.
SELECT t1.FK,
t1.Priority,
StartDate = t1.PriorityUpdateDateTime,
EndDate =
(
SELECT MIN(t2.PriorityUpdateDateTime)
FROM #Test t2
WHERE t2.FK = t1.FK
AND t2.PriorityUpdateDateTime > t1.PriorityUpdateDateTime
)
FROM #Test t1
ORDER BY t1.FK, t1.PriorityUpdateDateTime, t1.Priority
;
--===== Or, you could use a CROSS APPLY and get the same thing because
-- a CROSS APPLY isn't much more than a correlated sub-query.
SELECT t1.FK,
t1.Priority,
StartDate = t1.PriorityUpdateDateTime,
d.EndDate
FROM #Test t1
CROSS APPLY
(
SELECT MIN(t2.PriorityUpdateDateTime)
FROM #Test t2
WHERE t2.FK = t1.FK
AND t2.PriorityUpdateDateTime > t1.PriorityUpdateDateTime
) d (EndDate)
ORDER BY t1.FK, t1.PriorityUpdateDateTime, t1.Priority
;