Como posso ter várias expressões de tabela comuns em uma única instrução SELECT?

92

Estou no processo de simplificar uma instrução select complicada, então pensei em usar expressões de tabela comuns.

Declarar um único cte funciona bem.

WITH cte1 AS (
    SELECT * from cdr.Location
    )

select * from cte1 

É possível declarar e usar mais de um cte no mesmo SELECT?

ou seja, este sql dá um erro

WITH cte1 as (
    SELECT * from cdr.Location
)

WITH cte2 as (
    SELECT * from cdr.Location
)

select * from cte1    
union     
select * from cte2

o erro é

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. Eu tentei colocar ponto-e-vírgulas e obtive este erro

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

Provavelmente não é relevante, mas isso é no SQL 2008.

Paul Rowland
fonte

Respostas:

139

Eu acho que deveria ser algo como:

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

Basicamente, WITHé apenas uma cláusula aqui e, como as outras cláusulas que recebem listas, "," é o delimitador apropriado.

MarkusQ
fonte
Fantástico. Eu estava enchendo tabelas temporárias com os resultados do CTE e combinando mais tarde, mas tive problemas com ponto e vírgula ao empacotar em um procedimento armazenado. Belo método!
Tom Halladay
18
Não se esqueça de que cte2pode fazer referência cte1a: ... cte2 as (SELECT * FROM cte1 WHERE ...)
Chahk
Herói! Isso me deixou perplexo por horas
bjpelcdev,
2
que tal declarar expressões recursivas e não recursivas?
Dmitry Volkov de
14

A resposta acima mencionada está certa:

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

Além disso, você também pode consultar de cte1 em 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 são apenas suposições para expressões.

Espero que este blog também ajude: http://iamfixed.blogspot.de/2017/11/common-table-expression-in-sql-with.html

Sagar Dev Timilsina
fonte
que tal declarar expressões recursivas e não recursivas?
Dmitry Volkov de