Ada agregat tidak berdokumen
disebut ANY
yang bukan sintaks yang valid tetapi dimungkinkan untuk muncul dalam rencana eksekusi Anda. Namun, ini tidak memberikan keuntungan kinerja apa pun.
Dengan asumsi tabel dan struktur indeks berikut
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
Saya juga telah mengisi data sampel sehingga ada banyak baris per grup.
Permintaan asli Anda
SELECT MAX(id),
[group]
FROM T
GROUP BY [group]
Memberikan Table 'T'. Scan count 1, logical reads 1367
dan rencananya
|--Stream Aggregate(GROUP BY:([[T].[group]) DEFINE:([Expr1003]=MAX([[T].[id])))
|--Index Scan(OBJECT:([[T].[ix]), ORDERED FORWARD)
Ditulis ulang untuk mendapatkan ANY
agregat...
;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
Memberikan Table 'T'. Scan count 1, logical reads 1367
dan rencananya
|--Stream Aggregate(GROUP BY:([[T].[group]) DEFINE:([[T].[id]=ANY([[T].[id])))
|--Index Scan(OBJECT:([[T].[ix]), ORDERED FORWARD)
Meskipun berpotensi SQL Server dapat berhenti memproses grup segera setelah nilai pertama ditemukan dan melompat ke yang berikutnya tidak. Itu masih memproses semua baris dan pembacaan logisnya sama.
Untuk contoh khusus ini dengan banyak baris dalam grup, versi yang lebih efisien adalah CTE rekursif.
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);
Yang memberi
Table 'Worktable'. Scan count 2, logical reads 19
Table 'T'. Scan count 4, logical reads 12
Pembacaan logis jauh lebih sedikit karena mengambil baris pertama per grup kemudian mencari ke grup berikutnya daripada membaca banyak catatan yang tidak berkontribusi pada hasil akhir.