したがって、私がWITH
使用した方法と、MSDNのドキュメントに基づいています。
共通テーブル式(CTE)と呼ばれる、一時的な名前付き結果セットを指定します。
はテーブルWITH
の代わりのようです。#TEMP
あれは正しいですか?
したがって、私がWITH
使用した方法と、MSDNのドキュメントに基づいています。
共通テーブル式(CTE)と呼ばれる、一時的な名前付き結果セットを指定します。
はテーブルWITH
の代わりのようです。#TEMP
あれは正しいですか?
いいえ。CTE(によって導入されたWITH
)は一時テーブルを置き換えませんが、過去に一時テーブルを使用したことがある場合に使用できる場合もあります。
WITH
は実際には派生テーブルにすぎませんが、インラインではなくクエリの前に導入され、クエリ全体でテーブルとして複数回使用できるエイリアスが与えられるという違いがあります。
派生テーブルは、括弧内の完全なクエリであり、実際のテーブルであるかのように使用されます。ビューとテーブル値関数も派生テーブルと見なされますが、インラインで定義される種類に焦点を当てています。次に例を示します。
SELECT
C.Name,
S.SalesTotal
FROM
dbo.Customer C
INNER JOIN (
SELECT
O.CustomerID,
SalesTotal = Sum(OrderTotal)
FROM
dbo.CustomerOrder O
GROUP BY
O.CustomerID
) S
ON C.CustomerID = S.CustomerID;
独自の行セット(GROUP BY
クエリ)を返す完全に無傷のクエリがあります。これを括弧の中に入れてエイリアスを割り当てることでS
、テーブルのように使用できるようになります。これにさらに多くのテーブルを結合することができます。ただし、このテーブルに参加したのは1回だけです。
これをCTEに変換するには、非常に簡単な変更を加えます。
WITH SalesTotals AS (
SELECT
O.CustomerID,
SalesTotal = Sum(OrderTotal)
FROM
dbo.CustomerOrder O
GROUP BY
O.CustomerID
)
SELECT
C.Name,
S.SalesTotal
FROM
dbo.Customer C
INNER JOIN SalesTotals S
ON C.CustomerID = S.CustomerID
-- and for an example of using the CTE twice:
INNER JOIN (
SELECT Avg(SalesTotal)
FROM SalesTotals
) A (AverageSalesTotal)
ON S.SalesTotal >= A.AverageSalesTotal;
さて、臨時雇用者テーブルは完全に異なる動物です。CTEまたは派生テーブルとは非常に重要な違いがあります。
Avg(SalesTotal)
少なくとも2012年までのバージョンのSQL Serverでの計算には、SalesTotals
集計を2回実行するという完全に別個の操作が含まれます。エンジンがCTEの結果を具体化することは可能ですが、これまでのところSQLServerはこれを実行していません。Oracleなどの他のDBMSがCTEの結果を具体化する可能性があることは注目に値します。いずれにせよ、この二重クエリは(もちろん!)パフォーマンスに深刻な影響を与える可能性があることに注意する必要があります。最後に、CTEは、一時テーブルでは実行できないことを実行できます。再帰的である可能性があります。Oracleでは、これはによって表現されCONNECT BY
、SQL ServerではUNION ALL SELECT
、CTE自体のエイリアスを参照できるCTEの内部で実行されます。
CTEには注意してください。CTEは優れた抽象化ですが、それ以上のものではなく、深刻な問題に遭遇する可能性があります。一度に1行ずつ再帰CTEを使用して100万行を生成できますが、これは100倍以上の最悪の方法です。
SQL Server 2005以降には、「テーブル変数」と呼ばれる別の特別な種類の一時テーブルがあります。これは、いくつかの注目すべき例外を除いて、一時テーブルに非常によく似ています(tempdbにまったく同じに保持されます)。
SQLオプティマイザーは、今日、優れた実行プランを選択する上ではるかに優れた仕事をしますが、特にいくつかの大きなテーブルとビューで10を超えるテーブルを結合し、複数のフィルターを使用する必要がある場合、最適に実行されないことがよくあります。#TEMPテーブルを使用し、クエリを結合する前にクエリをはるかに小さなサブセットに分割するほど高速なものはまだありません。注:#TEMPテーブルにインデックスを追加するとパフォーマンスが向上することはめったにありません。
いいえ、それは正しくありません。これらは両方とも別個の機能であり、それぞれに個別の用途があります。
たとえば、CTEは小さなデータに適していますが、一時テーブルは通常、大きなデータセットに適しています。一時テーブルにはインデックスを付けてパフォーマンスを向上させることができますが、CTEではできません。
MSDNのドキュメントを読み、どちらか一方を使用する特定のインスタンスを確認するのに少し時間を費やします。