Un simple auto unirse parecería realizar mucho mejor que una fila referencia subconsulta
Generar 10k filas de datos de prueba:
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
Me tire el caso especial de las 3 primeras filas de la consulta principal, puede UNION TODOS los que volverán si realmente lo quiere en la fila establecida. Auto consulta de combinació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
En mi máquina esto tarda unos 10 segundos, el enfoque subconsulta que Aaron Alton demostró tarda unos 45 segundos (después de cambiar para reflejar mi mesa fuente de prueba):
;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
Si realiza un PERFIL DE ESTADÍSTICAS CONECTADO ENCENDIDO, puede ver que la autocomunicación tiene ejecuciones de 10k en el spool de la tabla. La subconsulta tiene ejecuciones de 10k en el filtro, el agregado y otros pasos.
¿Qué tipo de base de datos SQL está utilizando? –
Estoy usando SQL Server 2008. – HYP
Estoy pensando que este es uno de esos casos realmente raros donde los cursores van a ser más rápidos ... solo mantenga las últimas 3 filas en vars ... –