シンプルに保ち、クエリで複数のCTEを実行する方法


156

この単純なT-SQLクエリを使用すると、テーブルから一連の列が出力され、他の関連テーブルの情報も結合されます。

私のデータモデルは単純です。参加者と一緒に予定されているイベントがあります。各イベントに参加する参加者の人数を知る必要があります。

これに対する私の解決策は、スケジュールされたイベントをグループ化し、参加者の数をカウントするCTEを追加することです。

これにより、予定されているイベントごとにその情報に参加できます。クエリをシンプルに保つ。

クエリを単純にしたいのですが、将来、単純なクエリ中に一時的な結果にアクセスできるようにする必要がある場合はどうすればよいですか?

複数のCTEを持つことができてもできない場合は、本当にそれを望みます。ここに私のオプションは何ですか?

ビューを除外し、アプリケーションデータレイヤーで処理を実行しました。SQLクエリを分離することを好みます。

回答:


297

CTE1つのクエリで複数のを使用したり、を再利用したりできCTEます。

WITH    cte1 AS
        (
        SELECT  1 AS id
        ),
        cte2 AS
        (
        SELECT  2 AS id
        )
SELECT  *
FROM    cte1
UNION ALL
SELECT  *
FROM    cte2
UNION ALL
SELECT  *
FROM    cte1

ただし、アクセスされるたびにSQL Server再評価される可能性があるCTEためRAND()NEWID()などの値を使用している場合、CTE呼び出し間で値が変わる可能性があることに注意してください。


3
とても簡単でした。MSDNのドキュメントはこの問題について少しあいまいでしたが、決定的なものは見つかりませんでした。どうもありがとうございました!
John Leidegren

1
これは、WITH common_table_expression(Transact-SQL)に記載されています。あなたは、これは(の特別なノート取る構文セクションにあります見ることができます[ ,...n ]では[ WITH <common_table_expression> [ ,...n ] ]、明示的にこれを呼び出す「単一のクエリで複数のCTE定義の使用」。例Cを、。悲しいことに、この例では、SQL 2008との資料に記載されていません古い(つまり、OPが質問を投稿したときに例が提供されていなかった)
Brian

これでレコードの量が2倍になります:/
Tom Stickel

@TomStickelは最後のクエリの前に、クエリの半分だけを使用してみますUNION ALL
Quassnoi

@Quassnoiはい、うまくいきました。私はコメントを書いた後でそれをしました。なぜその2番目のユニオンがそこにあるのかわからない...
Tom Stickel

90

単一のクエリ式に複数のCTEを含めることができます。それらをカンマで区切る必要があります。例を示します。以下の例では、2つのCTEがあります。1つは名前が付けられCategoryAndNumberOfProducts、もう1つはという名前ProductsOverTenDollarsです。

WITH CategoryAndNumberOfProducts (CategoryID, CategoryName, NumberOfProducts) AS
(
   SELECT
      CategoryID,
      CategoryName,
      (SELECT COUNT(1) FROM Products p
       WHERE p.CategoryID = c.CategoryID) as NumberOfProducts
   FROM Categories c
),

ProductsOverTenDollars (ProductID, CategoryID, ProductName, UnitPrice) AS
(
   SELECT
      ProductID,
      CategoryID,
      ProductName,
      UnitPrice
   FROM Products p
   WHERE UnitPrice > 10.0
)

SELECT c.CategoryName, c.NumberOfProducts,
      p.ProductName, p.UnitPrice
FROM ProductsOverTenDollars p
   INNER JOIN CategoryAndNumberOfProducts c ON
      p.CategoryID = c.CategoryID
ORDER BY ProductName

5
@JohnLeidegren:最初の正解から2分以内に正解を投稿することは、少なくとも私が与えた賛成票に値します。
ピーターマジード
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.