2011-03-25 80 views
13

我在的SQLServer 2008該聲明的臨時表,並用它來計算內部與vs一起使用聲明臨時表:性能/差異?

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 

上的值的移動平均線,但我也發現了,你可以聲明不是Temptable這樣創建的SQL函數:

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

問:這兩種方法有什麼主要區別嗎?比其他或更常見/標準更快嗎?因爲你定義了你正在尋找的列是什麼,所以我認爲declare更快。如果我要省略在移動平均數的計算中未使用的列,它會更快嗎?(不確定這個一個因爲它必須得到所有的行反正,但選擇較少的列使直覺感覺它會更快/更少做)

我也從這裏找到了create temporary table @tableHow to declare Internal table in MySQL?但我不想要表(我不確定創建臨時表是否執行此操作)

+0

下面是運行平均值的兩個示例,不需要臨時表,您可能希望嘗試以獲得可能的性能改進:https://stackoverflow.com/questions/911326/sql-select-statement-for-calculating -a-running-average-column https:// stackoverflow。com/questions/26618353/t-sql-calculate-moving-average – 2017-06-06 02:13:19

回答

24

@table語法創建表變量(tempdb中的實際表),並將結果實現爲它。

WITH語法定義了一個Common Table Expression,它沒有物化,只是一個內聯視圖。

大多數情況下,您最好使用第二個選項。你提到這是在一個函數中。如果這是一個TVF,那麼大多數時候你希望它們是內聯而不是多語句,這樣它們可以被優化器擴展出來 - 這會立即禁止使用表變量。然而,有時候(例如,底層查詢很貴,而且您希望避免它被多次執行),您可能會確定在某些特定情況下實現中間結果可以提高性能。有currently no way迫使這CTE(without forcing a plan guide at least

在這種情況下,你(一般)有3個選項。 A @tablevariable#localtemp表和##globaltemp表。然而,只有第一個允許在函數內部使用。

有關表變量和#temp表see here之間差異的更多信息。

+1

還提到#temp和## temp表類型以供參考 – SQLMenace 2011-03-25 16:37:31

+0

@SQLMenace - 已完成但我剛剛注意到OP正在使用此功能,因此贏得了不能使用這些... – 2011-03-25 17:00:39

+0

所以你不能使用函數內的#或##嗎?是的,這是一個TVF,他們在線是什麼意思?只需要使用WITH語法? – Mike 2011-03-25 17:34:28

9

除了什麼馬丁回答

;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 

也可以寫成這樣

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

感謝您的解釋與,我曾認爲它會做類似的事情,但不確定 – Mike 2011-03-25 17:35:57

0

另一個區別是第二種方式(with tableName as ...)結果只讀臨時表。但在第一種方式(declare table)您可以更改您的表格數據。