As the accepted answer correctly says, the with
clause is used only once per a CTE chain. However, for sake of completeness, I would like to add it does not stop you from nesting CTEs.
If cte2
uses cte1
, cte3
uses cte2
etc., then the dependency chain between CTEs is linear and it is expressed as with
with 3 CTEs. On the contrary, if cte2
doesn't need cte1
and both are needed only in cte3
it should be considered to nest them under definition of cte3
(with cte3 as (with cte1 as (...), cte2 as (...) select...)
).
The syntax of CTEs then reflects the dependency tree between CTEs and literally visualizes the scope of partial datasets which can improve readability and prevents scope leakage bugs. Not all db vendors support it but Postgres does.
Example:
with cte1(id,capital) as (
values(1,'Prague'),(2,'Bratislava')
), cte2(id,code) as (
with cte2inner1(id,code) as (
values(1,'CZ'),(2,'SK')
), cte2inner2(id,country) as (
values(1,'Czech Republic'),(2,'Slovakia')
)
select id,country from cte2inner1 join cte2inner2 using (id)
)
select *
from cte1 join cte2 using (id)
--join cte2inner1 not possible here