Semplificando e come eseguire più CTE in una query


156

Ho questa semplice query T-SQL, emette un mucchio di colonne da una tabella e unisce anche informazioni da altre tabelle correlate .

Il mio modello di dati è semplice. Ho un evento in programma, con i partecipanti. Devo sapere quanti partecipanti partecipano a ciascun evento.

La mia soluzione a questo è quella di aggiungere un CTE che raggruppa gli eventi programmati e conta il numero di partecipanti.

Questo mi permetterà di unirmi a tali informazioni per evento programmato. Mantenere la query semplice.

Mi piace mantenere semplici le mie domande, tuttavia, se in futuro dovessi avere risultati temporanei aggiuntivi accessibili durante la mia semplice query, cosa devo fare?

Mi piacerebbe davvero, se potessi avere più CTE ma non posso, giusto? quali sono le mie opzioni?

Ho escluso le visualizzazioni e le operazioni a livello di dati dell'applicazione. Preferisco isolare le mie query SQL.

Risposte:


297

Puoi avere più messaggi CTEin una query, oltre a riutilizzare 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

Si noti, tuttavia, che SQL Serverpotrebbe rivalutare CTEogni volta che si accede, quindi se si utilizzano valori come RAND(), NEWID()ecc., Potrebbero cambiare tra le CTEchiamate.


3
Era così semplice. la documentazione MSDN era un po 'confusa riguardo al problema, non riuscivo a trovare nulla di conclusivo. Grazie mille!
John Leidegren,

1
È documentato in WITH common_table_expression (Transact-SQL) . Si può vedere questo sono nella sezione di sintassi (prendere nota speciale del [ ,...n ]in [ WITH <common_table_expression> [ ,...n ] ]. Esempio C, "Uso di più definizioni di CTE in una singola query," richiede questo fuori in modo esplicito. Purtroppo, questo esempio non viene fornito nella documentazione per SQL 2008 e più vecchio (ovvero, l'esempio non è stato fornito quando l'OP ha pubblicato la domanda).
Brian

Ottengo il doppio della quantità di record su questo: /
Tom Stickel

@TomStickel prova solo a utilizzare la metà della query, prima dell'ultimaUNION ALL
Quassnoi

@Quassnoi Sì, ha funzionato. L'ho fatto dopo aver scritto il commento. Non sono sicuro del perché quella seconda unione sia presente ...
Tom Stickel,

90

Sicuramente puoi avere più CTE in una singola espressione di query. Hai solo bisogno di separarli con una virgola. Ecco un esempio Nell'esempio seguente, ci sono due CTE. Uno è chiamato CategoryAndNumberOfProductse il secondo è chiamato 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: pubblicare una risposta corretta entro 2 minuti dalla prima risposta corretta merita un voto, che ho dato, almeno.
Peter Majeed,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.