回答:
1つの例として、同じデータセットを複数回参照/結合する必要がある場合は、CTEを定義することで実行できます。したがって、これはコードの再利用の一形態になる可能性があります。
自己参照の例は再帰です:CTEを使用した再帰クエリ
Books Onlineから取られたエキサイティングなMicrosoftの定義の場合 :
CTEは次の目的で使用できます。
再帰クエリを作成します。詳細については、「共通テーブル式を使用した再帰クエリ」を参照してください。
ビューの一般的な使用が不要な場合は、ビューを置き換えます。つまり、定義をメタデータに保存する必要はありません。
スカラー副選択から派生した列によるグループ化、または確定的でないか外部アクセスが可能な関数によるグループ化を有効にします。
同じステートメントで、結果のテーブルを複数回参照します。
select top 100 * into #tmp from master..spt_values order by 1,2,3,4 select A.number, COUNT(*) from #tmp A inner join #tmp B ON A.number = B.number+1 group by A.number
vswith CTE AS (select top 100 * from master..spt_values order by 1,2,3,4) select A.number, COUNT(*) from CTE A inner join CTE B ON A.number = B.number+1 group by A.number
それらを使用して、複雑なクエリ、特に複雑な結合とサブクエリを分割します。クエリの意図を理解するのに役立つように、それらを「疑似ビュー」としてますます使用しています。
それらについての私の唯一の不満はそれらが再利用できないことです。たとえば、同じCTEを使用できる2つの更新ステートメントを含むストアドプロシージャがあるとします。ただし、CTEの「範囲」は最初のクエリのみです。
問題は、「簡単な例」ではおそらくCTEは実際には必要ないということです。
それでも、非常に便利です。
VIEW
:)の候補と見なされるべきです
cteを使用する理由は2つあります。
where句で計算値を使用する。これは、派生テーブルよりも少しクリーンに思えます。
2つのテーブルがあるとします-Questions.ID = Answers.Question_Id(およびクイズID)によって結合された質問と回答
WITH CTE AS
(
Select Question_Text,
(SELECT Count(*) FROM Answers A WHERE A.Question_ID = Q.ID) AS Number_Of_Answers
FROM Questions Q
)
SELECT * FROM CTE
WHERE Number_Of_Answers > 0
質問と回答のリストを取得する別の例を次に示します。回答を結果の質問と一緒にグループ化してください。
WITH cte AS
(
SELECT [Quiz_ID]
,[ID] AS Question_Id
,null AS Answer_Id
,[Question_Text]
,null AS Answer
,1 AS Is_Question
FROM [Questions]
UNION ALL
SELECT Q.[Quiz_ID]
,[Question_ID]
,A.[ID] AS Answer_Id
,Q.Question_Text
,[Answer]
,0 AS Is_Question
FROM [Answers] A INNER JOIN [Questions] Q ON Q.Quiz_ID = A.Quiz_ID AND Q.Id = A.Question_Id
)
SELECT
Quiz_Id,
Question_Id,
Is_Question,
(CASE WHEN Answer IS NULL THEN Question_Text ELSE Answer END) as Name
FROM cte
GROUP BY Quiz_Id, Question_Id, Answer_id, Question_Text, Answer, Is_Question
order by Quiz_Id, Question_Id, Is_Question Desc, Name
HAVING
サブを使用して同様とすることができる後期フィルタを行うための別の方法ですSELECT
CTEを使用すると便利だとわかったシナリオの1つは、1つ以上の列に基づいてDISTINCT行のデータを取得したいが、テーブル内のすべての列を返したい場合です。標準クエリでは、最初に個別の値を一時テーブルにダンプしてから、それらを元のテーブルに結合して残りの列を取得するか、結果を返すことができる非常に複雑なパーティションクエリを作成する必要がある場合があります。 1回実行されますが、ほとんどの場合、読み取り不可能でパフォーマンスの問題が発生します。
ただし、CTEを使用する(レコードの最初のインスタンスの選択で Tim Schmelterが回答)
WITH CTE AS(
SELECT myTable.*
, RN = ROW_NUMBER()OVER(PARTITION BY patientID ORDER BY ID)
FROM myTable
)
SELECT * FROM CTE
WHERE RN = 1
ご覧のとおり、これは読みやすく、保守しやすいものです。そして、他のクエリと比較して、パフォーマンスがはるかに優れています。
おそらく、CTEを単一のクエリに使用されるビューの代わりとして考える方がより意味があります。ただし、オーバーヘッド、メタデータ、または正式なビューの永続性は必要ありません。次のような場合に非常に役立ちます。
これは、カットアンドペーストの例です。
WITH [cte_example] AS (
SELECT 1 AS [myNum], 'a num' as [label]
UNION ALL
SELECT [myNum]+1,[label]
FROM [cte_example]
WHERE [myNum] <= 10
)
SELECT * FROM [cte_example]
UNION
SELECT SUM([myNum]), 'sum_all' FROM [cte_example]
UNION
SELECT SUM([myNum]), 'sum_odd' FROM [cte_example] WHERE [myNum] % 2 = 1
UNION
SELECT SUM([myNum]), 'sum_even' FROM [cte_example] WHERE [myNum] % 2 = 0;
楽しい
今日は、SQL Server 2005で導入され、以降のバージョンでも利用できる新機能である共通テーブル式について学習します。
共通テーブル式:-共通テーブル式は、一時的な結果セット、つまりSQL Serverのビューの代替として定義できます。共通テーブル式は、それが定義されたステートメントのバッチでのみ有効であり、他のセッションでは使用できません。
CTE(共通テーブル式)を宣言する構文:-
with [Name of CTE]
as
(
Body of common table expression
)
例を挙げましょう:-
CREATE TABLE Employee([EID] [int] IDENTITY(10,5) NOT NULL,[Name] [varchar](50) NULL)
insert into Employee(Name) values('Neeraj')
insert into Employee(Name) values('dheeraj')
insert into Employee(Name) values('shayam')
insert into Employee(Name) values('vikas')
insert into Employee(Name) values('raj')
CREATE TABLE DEPT(EID INT,DEPTNAME VARCHAR(100))
insert into dept values(10,'IT')
insert into dept values(15,'Finance')
insert into dept values(20,'Admin')
insert into dept values(25,'HR')
insert into dept values(10,'Payroll')
従業員と部署の2つのテーブルを作成し、各テーブルに5行挿入しました。次に、これらのテーブルを結合して、さらに使用するための一時的な結果セットを作成します。
With CTE_Example(EID,Name,DeptName)
as
(
select Employee.EID,Name,DeptName from Employee
inner join DEPT on Employee.EID =DEPT.EID
)
select * from CTE_Example
ステートメントの各行を1つずつ理解してみましょう。
CTEを定義するには、「with」句を記述してから、テーブル式に名前を付けます。ここでは、「CTE_Example」という名前を付けています。
次に、 "As"を記述し、コードを2つの角かっこ(---)で囲みます。角かっこで複数のテーブルを結合できます。
最後の行では、「Select * from CTE_Example」を使用しました。コードの最後の行でCommonテーブル式を参照しているため、ビューのように定義でき、単一のビューを使用していると言えます。バッチとCTEは永続的なオブジェクトとしてデータベースに保存されません。しかし、それはビューのように動作します。CTEで削除および更新ステートメントを実行できます。これは、CTEで使用されている参照テーブルに直接影響します。この事実を理解するために例を見てみましょう。
With CTE_Example(EID,DeptName)
as
(
select EID,DeptName from DEPT
)
delete from CTE_Example where EID=10 and DeptName ='Payroll'
上記のステートメントでは、CTE_Exampleから行を削除しており、CTEで使用されている参照テーブル "DEPT"からデータを削除します。
「順序付けされた更新」を実行する場合に非常に便利です。
MS SQLでは、UPDATEでORDER BYを使用することはできませんが、CTEを使用すると、次のように実行できます。
WITH cte AS
(
SELECT TOP(5000) message_compressed, message, exception_compressed, exception
FROM logs
WHERE Id >= 5519694
ORDER BY Id
)
UPDATE cte
SET message_compressed = COMPRESS(message), exception_compressed = COMPRESS(exception)
詳細はこちらをご覧ください:ms sqlを使用して更新および注文する方法
まだ指摘されていない1つのポイントは、速度です。私はそれが古い回答の質問であることを知っていますが、これは直接のコメント/回答に値すると思います:
派生テーブルでも同じことができるので、冗長であるように見える
初めてCTEを使用したとき、その速度にまったく驚かされました。教科書のようなケースで、CTEに非常に適していましたが、CTEを使用したすべての場面で、大幅な速度の向上がありました。最初のクエリは派生テーブルで複雑で、実行に長い時間がかかりました。CTEを使用すると、ほんの数秒しかかかりませんでした。