web-dev-qa-db-fra.com

Rester simple et savoir faire plusieurs CTE dans une requête

J'ai cette simple requête T-SQL, il émet un tas de colonnes à partir d'une table et joint également des informations à partir d'autres tables liées.

Mon modèle de données est simple. J'ai un événement programmé avec les participants. J'ai besoin de savoir combien de participants participent à chaque événement.

Ma solution consiste à ajouter un CTE qui regroupe les événements planifiés et compte le nombre de participants.

Cela me permettra de joindre ces informations pour chaque événement planifié. Garder la requête simple.

Cependant, j'aime garder mes requêtes simples. Si, à l'avenir, j'ai besoin de disposer de résultats temporaires supplémentaires accessibles pendant ma requête simple, que dois-je faire?

Je l’aimerais vraiment, si je pouvais avoir plusieurs CTE mais je ne peux pas, non? Quelles sont mes options ici?

J'ai exclu des vues et des actions au niveau de la couche de données d'application. Je préfère isoler mes requêtes SQL.

131
John Leidegren

Vous pouvez avoir plusieurs CTEs dans une même requête, ainsi que réutiliser un 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

Notez cependant que SQL Server peut réévaluer la CTE à chaque accès; ainsi, si vous utilisez des valeurs telles que Rand(), NEWID() etc., elles peuvent changer entre CTE appels.

251
Quassnoi

Vous pouvez certainement avoir plusieurs CTE dans une seule expression de requête. Vous avez juste besoin de les séparer avec une virgule. Voici un exemple. Dans l'exemple ci-dessous, il y a deux CTE. L'un s'appelle CategoryAndNumberOfProducts et le second s'appelle 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