Der er en udokumenteret aggregat
kaldet ANY
som ikke er gyldig syntaks, men det er muligt at få vist i dine eksekveringsplaner. Dette giver dog ingen ydeevnefordele.
Forudsat følgende tabel- og indeksstruktur
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
Jeg har også udfyldt med eksempeldata, så der er mange rækker pr. gruppe.
Din oprindelige forespørgsel
SELECT MAX(id),
[group]
FROM T
GROUP BY [group]
Giver Table 'T'. Scan count 1, logical reads 1367
og planen
|--Stream Aggregate(GROUP BY:([[T].[group]) DEFINE:([Expr1003]=MAX([[T].[id])))
|--Index Scan(OBJECT:([[T].[ix]), ORDERED FORWARD)
Omskrevet for at få ANY
samlet...
;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
Giver Table 'T'. Scan count 1, logical reads 1367
og planen
|--Stream Aggregate(GROUP BY:([[T].[group]) DEFINE:([[T].[id]=ANY([[T].[id])))
|--Index Scan(OBJECT:([[T].[ix]), ORDERED FORWARD)
Selvom SQL Server potentielt kunne stoppe med at behandle gruppen, så snart den første værdi er fundet og springe til den næste, gør den det ikke. Den behandler stadig alle rækker, og de logiske læsninger er de samme.
For dette særlige eksempel med mange rækker i gruppen ville en mere effektiv version være en rekursiv CTE.
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);
Hvilket giver
Table 'Worktable'. Scan count 2, logical reads 19
Table 'T'. Scan count 4, logical reads 12
De logiske læsninger er meget mindre, da den henter den første række pr. gruppe og derefter søger ind i den næste gruppe i stedet for at læse en mængde poster, der ikke bidrager til det endelige resultat.