Một tự đơn giản tham gia sẽ có vẻ để thực hiện tốt hơn nhiều so với một hàng tham khảo subquery
Tạo 10k dòng dữ liệu thử nghiệm:
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
tôi sẽ kéo trường hợp đặc biệt của 3 hàng đầu tiên trong số các truy vấn chính, bạn có thể UNION TẤT CẢ những người trở lại trong nếu bạn thực sự muốn nó trong tập hợp hàng. Tự tham gia truy vấn:
;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
Trên máy tính của tôi này mất khoảng 10 giây, cách tiếp cận subquery đó Aaron Alton chứng minh mất khoảng 45 giây (sau khi tôi thay đổi nó để phản ánh kiểm tra bảng nguồn của tôi):
;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
Nếu bạn làm một SET STATISTICS PROFILE ON, bạn có thể thấy tự join có 10k thực hiện trên spool bảng. Truy vấn con có 10k thực thi trên bộ lọc, tổng hợp và các bước khác.
Bạn đang sử dụng loại cơ sở dữ liệu SQL nào? –
Tôi đang sử dụng SQL Server 2008. – HYP
Im nghĩ đây là một trong những trường hợp hiếm hoi mà con trỏ sẽ nhanh nhất ... chỉ cần giữ 3 hàng cuối cùng trong vars ... –