Comment puis-je avoir plusieurs expressions de table communes dans une seule instruction SELECT?

93

Je suis en train de simplifier une instruction de sélection compliquée, alors j'ai pensé utiliser des expressions de table communes.

Déclarer un seul cte fonctionne bien.

WITH cte1 AS (
    SELECT * from cdr.Location
    )

select * from cte1 

Est-il possible de déclarer et d'utiliser plus d'un cte dans le même SELECT?

ie ce sql donne une erreur

WITH cte1 as (
    SELECT * from cdr.Location
)

WITH cte2 as (
    SELECT * from cdr.Location
)

select * from cte1    
union     
select * from cte2

l'erreur est

Msg 156, Level 15, State 1, Line 7
Incorrect syntax near the keyword 'WITH'.
Msg 319, Level 15, State 1, Line 7
Incorrect syntax near the keyword 'with'. If this statement is a common table expression, an xmlnamespaces clause or a change tracking context clause, the previous statement must be terminated with a semicolon.

NB. J'ai essayé de mettre des points-virgules et d'obtenir cette erreur

Msg 102, Level 15, State 1, Line 5
Incorrect syntax near ';'.
Msg 102, Level 15, State 1, Line 9
Incorrect syntax near ';'.

Probablement pas pertinent mais c'est sur SQL 2008.

Paul Rowland
la source

Réponses:

140

Je pense que ça devrait être quelque chose comme:

WITH 
    cte1 as (SELECT * from cdr.Location),
    cte2 as (SELECT * from cdr.Location)
select * from cte1 union select * from cte2

Fondamentalement, ce WITHn'est qu'une clause ici, et comme les autres clauses qui prennent des listes, "," est le délimiteur approprié.

MarkusQ
la source
C'est génial. J'avais rempli des tables temporaires avec les résultats du CTE et je les combinais plus tard, mais j'ai rencontré des problèmes avec les points virgules lors de l'empaquetage dans un processus stocké. Belle méthode!
Tom Halladay
18
N'oubliez pas que vous cte2pouvez faire référence cte1comme ceci: ... cte2 as (SELECT * FROM cte1 WHERE ...)
Chahk
Héros! Cela m'a
laissé
2
qu'en est-il de la déclaration d'expressions récursives et non récursives?
Dmitry Volkov
15

La réponse mentionnée ci-dessus est juste:

WITH 
    cte1 as (SELECT * from cdr.Location),
    cte2 as (SELECT * from cdr.Location)
select * from cte1 union select * from cte2

De plus, vous pouvez également interroger de cte1 dans cte2:

WITH 
    cte1 as (SELECT * from cdr.Location),
    cte2 as (SELECT * from cte1 where val1 = val2)

select * from cte1 union select * from cte2

val1,val2 ne sont que des hypothèses pour les expressions.

J'espère que ce blog aidera également: http://iamfixed.blogspot.de/2017/11/common-table-expression-in-sql-with.html

Sagar Dev Timilsina
la source
qu'en est-il de la déclaration d'expressions récursives et non récursives?
Dmitry Volkov