2010-01-26 2 views
79

J'ai cette simple requête T-SQL, il émet un tas de colonnes d'une table et joint également des informations d'autres tables .Rester simple et comment faire plusieurs CTE dans une requête

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

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

Cela me permettra de joindre cette information par événement planifié. Garder la requête simple. Je souhaite que mes requêtes soient simples, toutefois, si je devais à l'avenir avoir d'autres résultats temporaires accessibles pendant ma simple requête, que dois-je faire?

Je voudrais vraiment, si je pouvais avoir plusieurs CTE mais je ne peux pas, non? Quelles sont mes options ici? J'ai exclu des vues et faire des choses à la couche de données d'application. Je préfère isoler mes requêtes SQL.

Répondre

158

Vous pouvez avoir plusieurs CTE s dans une requête, ainsi que la réutilisation d'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 toutefois que SQL Server peut réévaluer la CTE chaque fois qu'il est accessible, donc si vous utilisez des valeurs comme RAND(), NEWID() etc., ils peuvent changer entre les CTE appels.

+1

C'était aussi simple que ça. la documentation MSDN était un peu flou autour de la question, je n'ai rien trouvé de concluant. Merci beaucoup! –

+1

Il est documenté dans [WITH common_table_expression (Transact-SQL)] (http://msdn.microsoft.com/fr-fr/library/ms175972.aspx). Vous pouvez le voir dans la section syntaxe (notez en particulier le '[, ... n]' dans '[WITH [, ... n]]'. Exemple C, "Utiliser plusieurs définitions CTE dans Malheureusement, cet exemple n'est pas fourni dans la documentation pour SQL 2008 et plus ancien (c'est-à-dire que l'exemple n'a pas été fourni lorsque l'OP a posté la question) – Brian

51

Vous pouvez certainement avoir plusieurs CTE dans une même 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 
+2

@JohnLeidegren: afficher une bonne réponse Dans les 2 minutes qui suivent la première bonne réponse mérite au moins un commentaire, ce que j'ai donné au moins –

+0

Quel commentaire inutile: "SO (stackoverflow) est assez fortement modéré" - et heureusement ce type n'est pas un des modérateurs. –

Questions connexes