SQLServer 2008で一時関数を宣言し、それを使用して内部の値の移動平均を計算するSQL関数を作成しました
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,-@windowDays + 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を次のように宣言できることもわかりました。
with tempTable as
(
select * from aces.dbo.fEDVisitCounts('ALL', null,DATEADD(DD,-7,'01-09-2010'),
'04-09-2010',0,130,null,1, 0)
)
質問:これら2つのアプローチに大きな違いはありますか? 1つは他のよりも一般的/標準よりも速いですか?探している列が何であるかを定義しているので、宣言の方が速いと思います。移動平均の計算で使用されなかった列を省略するには?
ここからcreate temporary table @table
も見つかりました MySQLで内部テーブルを宣言する方法は? ですが、関数の外でテーブルを永続化したくありません(一時的な作成かどうかはわかりません)テーブルはこれを行うかどうかを指定します。)
@table
構文は、テーブル変数(tempdb
内の実際のテーブル)を作成し、その変数に結果を具体化します。
WITH
構文は Common Table Expression を定義します。これは具体化されておらず、単なるインラインビューです。
ほとんどの場合、2番目のオプションを使用したほうがよいでしょう。あなたはこれが関数の中にあると述べました。これがTVFの場合、ほとんどの場合、これらをマルチステートメントではなくインラインにして、オプティマイザーで展開できるようにします。これにより、テーブル変数の使用が即座に禁止されます。
ただし、場合によっては(基になるクエリが高価で、複数回実行されないようにする場合など)、中間結果を具体化することで特定のケースでパフォーマンスが向上すると判断する場合があります。 現在、CTEにこれを強制する方法はありません ( 少なくとも計画ガイドを強制せずに )
その結果、あなたは(一般的に)3つのオプションを持っています。 A @tablevariable
、#localtemp
テーブルと##globaltemp
テーブル。ただし、関数内での使用が許可されているのは最初の1つだけです。
テーブル変数と#tempテーブル の違いに関する詳細については、こちら を参照してください。
マーティンの答えに加えて
;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
もう1つの違いは2番目の方法です(with tableName as ...
)は読み取り専用の一時テーブルになります。しかし、最初の方法(declare table
)テーブルデータを変更できます。