簡單的自我加入似乎表現得比行更好的參考子查詢
生成10,000行測試數據:
drop table test10k
create table test10k (Id int, Number int, constraint test10k_cpk primary key clustered (id))
;WITH digits AS (
SELECT 0 as Number
UNION SELECT 1
UNION SELECT 2
UNION SELECT 3
UNION SELECT 4
UNION SELECT 5
UNION SELECT 6
UNION SELECT 7
UNION SELECT 8
UNION SELECT 9
)
,numbers as (
SELECT
(thousands.Number * 1000)
+ (hundreds.Number * 100)
+ (tens.Number * 10)
+ ones.Number AS Number
FROM digits AS ones
CROSS JOIN digits AS tens
CROSS JOIN digits AS hundreds
CROSS JOIN digits AS thousands
)
insert test10k (Id, Number)
select Number, Number
from numbers
我會拉第3行的特殊情況下進行的主要的查詢,你可以聯合所有那些回來,如果你真的想要在行集。自連接查詢:
;WITH NumberedRows
AS
(
SELECT rta.*, row_number() OVER (ORDER BY rta.ID ASC) AS RowNumber
FROM test10k rta
)
SELECT nr.ID, nr.Number,
avg(trailing.Number) as MovingAverage
FROM NumberedRows nr
join NumberedRows as trailing on trailing.RowNumber between nr.RowNumber-3 and nr.RowNumber-1
where nr.Number > 3
group by nr.id, nr.Number
在我的機器上這需要大約10秒,子查詢的方法,阿龍奧爾頓證明需要約45秒(之後我改變了它,以反映我的測試源表):
;WITH NumberedRows
AS
(
SELECT rta.*, row_number() OVER (ORDER BY rta.ID ASC) AS RowNumber
FROM test10k rta
)
SELECT nr.ID, nr.Number,
CASE
WHEN nr.RowNumber <=3 THEN NULL
ELSE ( SELECT avg(Number)
FROM NumberedRows
WHERE RowNumber < nr.RowNumber
AND RowNumber >= nr.RowNumber - 3
)
END AS MovingAverage
FROM NumberedRows nr
如果您執行SET STATISTICS PROFILE ON,您可以看到自加入在桌面假脫機上執行10k。子查詢有10k在過濾器,聚合和其他步驟上執行。
你在使用什麼樣的SQL數據庫? – 2009-05-26 15:33:31
我正在使用SQL Server 2008. – HYP 2009-05-26 15:35:11
我認爲這是真正罕見的情況之一,遊標將會變得最快......只是保持最後3行在變量中... – 2009-05-26 15:36:58