web-dev-qa-db-ja.com

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

この単純なT-SQLクエリは、テーブルから多数の列を生成し、他の関連テーブルからの情報も結合します。

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

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

これにより、スケジュールされたイベントごとにその情報に参加できます。クエリをシンプルに保ちます。

クエリをシンプルに保つのが好きですが、将来、単純なクエリ中に追加の一時結果にアクセスできるようにする必要がある場合、どうすればよいですか?

複数のCTEを持つことはできても、できません。ここで私のオプションは何ですか?

私はビューを排除し、アプリケーションデータレイヤーで物事を行っています。 SQLクエリを分離することを好みます。

131
John Leidegren

1つのクエリに複数のCTEを含めることができ、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呼び出し。

251
Quassnoi

確かに、1つのクエリ式に複数の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
75
Randy Minder