2011-03-25 10 views
13

He creado una función de SQL en SQL Server 2008 que declaró una tabla temporal y lo utiliza para calcular un promedio móvil de los valores dentro deUsar con vs declarar una tabla temporal: rendimiento/diferencia?

declare @tempTable table 
    (
     GeogType nvarchar(5), 
     GeogValue nvarchar(7), 
     dtAdmission date, 
     timeInterval int, 
     fromTime nvarchar(5), 
     toTime nvarchar(5), 
     EDSyndromeID tinyint, 
     nVisits int 
    ) 
insert @tempTable select * from aces.dbo.fEDVisitCounts(@geogType, @hospID,DATEADD(DD,[email protected] + 1,@fromDate), 
       @toDate,@minAge,@maxAge,@gender,@nIntervalsPerDay, @nSyndromeID) 


    INSERT @table (dtAdmission,EDSyndromeID, MovingAvg) 
    SELECT list.dtadmission 
     , @nSyndromeID 
     , AVG(data.nVisits) as MovingAvg 
    from @tempTable as list 
     inner join @tempTable as data 
    ON list.dtAdmission between data.dtAdmission and DATEADD(DD,@windowDays - 1,data.dtAdmission) 
    where list.dtAdmission >= @fromDate 
    GROUP BY list.dtAdmission 

pero también descubrió que se puede declarar la TempTable como esto :

with tempTable as 
(
    select * from aces.dbo.fEDVisitCounts('ALL', null,DATEADD(DD,-7,'01-09-2010'), 
     '04-09-2010',0,130,null,1, 0) 
) 

pregunta: ¿hay una diferencia importante en estos dos enfoques? ¿Es uno más rápido que el otro o más común/estándar? Creo que la declaración es más rápida ya que define cuáles son las columnas que está buscando. ¿Sería incluso más rápido si omitiera las columnas que no se usaron en los cálculos del promedio móvil? (No estoy seguro de esto). uno ya que tiene que obtener todas las filas de todos modos, aunque seleccionar menos columnas tiene sentido intuitivo de que sería más rápido/menos que hacer)

También encontré create temporary table @table de aquí How to declare Internal table in MySQL? pero no quiero la tabla para persistir fuera de la función (no estoy seguro de si la tabla temporal crea esto o no).

+0

Aquí hay dos ejemplos de promedios en ejecución que no requieren una tabla temporal que quizás desee probar para posibles mejoras de rendimiento: https://stackoverflow.com/questions/911326/sql-select-statement-for-calculating -a-running-average-column https: // stackoverflow.com/questions/26618353/t-sql-calculate-moving-average –

Respuesta

24

La sintaxis @table crea una variable de tabla (una tabla real en tempdb) y materializa los resultados a eso.

La sintaxis WITH define un Common Table Expression que no se materializa y es solo una Vista en línea.

La mayoría de las veces será mejor que utilice la segunda opción. Mencionas que esto está dentro de una función. Si se trata de un TVF, la mayoría de las veces usted quiere que estos estén en línea en lugar de enunciados múltiples para que el optimizador pueda expandirlos, lo que imposibilitaría instantáneamente el uso de variables de tabla.

Sin embargo, a veces (supongamos que la consulta subyacente es costosa y desea evitar que se ejecute varias veces), puede determinar que la materialización de los resultados intermedios mejora el rendimiento en algunos casos específicos. Hay currently no way de forzar esto para CTE (without forcing a plan guide at least)

En esa eventualidad usted (en general) tiene 3 opciones. Una tabla @tablevariable, #localtemp y una tabla ##globaltemp. Sin embargo, solo el primero de estos está permitido para su uso dentro de una función.

Para obtener más información sobre las diferencias entre las variables de tabla y las tablas #temp see here.

+1

Mencione también los tipos de tabla #temp y ## temp como referencia – SQLMenace

+0

@SQLMenace - Listo pero acabo de notar que el OP está usando esto en una función tan ganada ¿Podrás usar estos ... –

+0

para que no puedas usar el # o ## dentro de una función? y sí, esto es un TVF, ¿qué quieres decir con que están en línea? ¿Solo que se debe usar la sintaxis CON? – Mike

9

Además de lo que Martin respondió

;with tempTable as 
(
    select * from aces.dbo.fEDVisitCounts('ALL', null,DATEADD(DD,-7,'01-09-2010'), 
     '04-09-2010',0,130,null,1, 0) 
) 

SELECT * FROM tempTable 

también se puede escribir como esto

SELECT * FROM 
(
    select * from aces.dbo.fEDVisitCounts('ALL', null,DATEADD(DD,-7,'01-09-2010'), 
     '04-09-2010',0,130,null,1, 0) 
) AS tempTable --now you can join here with other tables 
+0

Gracias por la explicación del, Pensé que haría algo similar a eso, pero no estaba seguro – Mike

0

Otra diferencia es la segunda manera (with tableName as ...) dan como resultado una tabla temporal de sólo lectura. Pero de la primera manera (declare table) puede cambiar los datos de su tabla.

Cuestiones relacionadas