Hay un agregado no documentado
llamado ANY
lo cual no es una sintaxis válida pero es posible que llegue a aparecer en sus planes de ejecución. Sin embargo, esto no proporciona ninguna ventaja de rendimiento.
Asumiendo la siguiente tabla y estructura de índice
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
También he rellenado datos de muestra de modo que hay muchas filas por grupo.
Su consulta original
SELECT MAX(id),
[group]
FROM T
GROUP BY [group]
Da Table 'T'. Scan count 1, logical reads 1367
y el plano
|--Stream Aggregate(GROUP BY:([[T].[group]) DEFINE:([Expr1003]=MAX([[T].[id])))
|--Index Scan(OBJECT:([[T].[ix]), ORDERED FORWARD)
Reescrito para obtener ANY
agregado...
;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
Da Table 'T'. Scan count 1, logical reads 1367
y el plano
|--Stream Aggregate(GROUP BY:([[T].[group]) DEFINE:([[T].[id]=ANY([[T].[id])))
|--Index Scan(OBJECT:([[T].[ix]), ORDERED FORWARD)
Aunque potencialmente SQL Server podría dejar de procesar el grupo tan pronto como se encuentre el primer valor y pasar al siguiente, no lo hace. Todavía procesa todas las filas y las lecturas lógicas son las mismas.
Para este ejemplo particular con muchas filas en el grupo, una versión más eficiente sería una CTE recursiva.
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);
Lo que da
Table 'Worktable'. Scan count 2, logical reads 19
Table 'T'. Scan count 4, logical reads 12
Las lecturas lógicas son mucho menores ya que recupera la primera fila por grupo y luego busca en el siguiente grupo en lugar de leer una carga de registros que no contribuyen al resultado final.