¿Cómo puedo tener varias expresiones de tabla comunes en una sola instrucción SELECT?

93

Estoy en el proceso de simplificar una declaración de selección complicada, así que pensé en usar expresiones de tabla comunes.

Declarar un solo cte funciona bien.

WITH cte1 AS (
    SELECT * from cdr.Location
    )

select * from cte1 

¿Es posible declarar y usar más de un cte en el mismo SELECT?

es decir, este sql da un error

WITH cte1 as (
    SELECT * from cdr.Location
)

WITH cte2 as (
    SELECT * from cdr.Location
)

select * from cte1    
union     
select * from cte2

el error es

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.

NÓTESE BIEN. He intentado poner punto y coma y aparece este error

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

Probablemente no sea relevante, pero esto está en SQL 2008.

Paul Rowland
fuente

Respuestas:

140

Creo que debería ser algo como:

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

Básicamente, WITHes solo una cláusula aquí, y como las otras cláusulas que toman listas, "," es el delimitador apropiado.

MarkusQ
fuente
Eso es genial. Había estado llenando tablas temporales con los resultados del CTE y combinando más tarde, pero encontré problemas con el punto y coma al empaquetar en un proceso almacenado. Buen método!
Tom Halladay
18
No olvide que cte2puede hacer referencia cte1así: ... cte2 como (SELECT * FROM cte1 WHERE ...)
Chahk
¡Héroe! Esto me ha
dejado
2
¿Qué hay de declarar expresiones recursivas y no recursivas?
Dmitry Volkov
15

La respuesta mencionada anteriormente es correcta:

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

Además, también puede consultar desde cte1 en 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 son solo suposiciones para expresiones ...

Espero que este blog también ayude: http://iamfixed.blogspot.de/2017/11/common-table-expression-in-sql-with.html

Sagar Dev Timilsina
fuente
¿Qué hay de declarar expresiones recursivas y no recursivas?
Dmitry Volkov