Có một tổng hợp không có giấy tờ
được gọi là ANY
đó không phải là cú pháp hợp lệ nhưng có thể xuất hiện trong các kế hoạch thực thi của bạn. Tuy nhiên, điều này không mang lại bất kỳ lợi thế nào về hiệu suất.
Giả sử cấu trúc bảng và chỉ mục sau
CREATE TABLE T
(
id int identity primary key,
[group] char(1)
)
CREATE NONCLUSTERED INDEX ix ON T([group])
INSERT INTO T
SELECT TOP 1000000 CHAR( 65 + ROW_NUMBER() OVER (ORDER BY @@SPID) % 3)
FROM sys.all_objects o1, sys.all_objects o2, sys.all_objects o3
Tôi cũng đã điền dữ liệu mẫu sao cho có nhiều hàng cho mỗi nhóm.
Truy vấn ban đầu của bạn
SELECT MAX(id),
[group]
FROM T
GROUP BY [group]
Cung cấp Table 'T'. Scan count 1, logical reads 1367
và kế hoạch
|--Stream Aggregate(GROUP BY:([[T].[group]) DEFINE:([Expr1003]=MAX([[T].[id])))
|--Index Scan(OBJECT:([[T].[ix]), ORDERED FORWARD)
Viết lại để lấy ANY
tổng hợp ...
;WITH cte AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY [group] ORDER BY [group] ) AS RN
FROM T)
SELECT id,
[group]
FROM cte
WHERE RN=1
Cung cấp Table 'T'. Scan count 1, logical reads 1367
và kế hoạch
|--Stream Aggregate(GROUP BY:([[T].[group]) DEFINE:([[T].[id]=ANY([[T].[id])))
|--Index Scan(OBJECT:([[T].[ix]), ORDERED FORWARD)
Mặc dù SQL Server có khả năng có thể ngừng xử lý nhóm ngay sau khi giá trị đầu tiên được tìm thấy và bỏ qua giá trị tiếp theo thì không. Nó vẫn xử lý tất cả các hàng và các lần đọc logic giống nhau.
Đối với ví dụ cụ thể này với nhiều hàng trong nhóm, phiên bản hiệu quả hơn sẽ là CTE đệ quy.
WITH RecursiveCTE
AS (
SELECT TOP 1 id, [group]
FROM T
ORDER BY [group]
UNION ALL
SELECT R.id, R.[group]
FROM (
SELECT T.*,
rn = ROW_NUMBER() OVER (ORDER BY (SELECT 0))
FROM T
JOIN RecursiveCTE R
ON R.[group] < T.[group]
) R
WHERE R.rn = 1
)
SELECT *
FROM RecursiveCTE
OPTION (MAXRECURSION 0);
Điều này mang lại cho
Table 'Worktable'. Scan count 2, logical reads 19
Table 'T'. Scan count 4, logical reads 12
Các lần đọc logic ít hơn nhiều vì nó truy xuất hàng đầu tiên trên mỗi nhóm sau đó tìm kiếm nhóm tiếp theo thay vì đọc một loạt các bản ghi không đóng góp vào kết quả cuối cùng.