单个查询中的多个CTE

时间:2016-02-07 00:17:37

标签: sql postgresql common-table-expression recursive-query arel

是否可以将单个查询中的多个CTE与arel组合在一起?我正在寻找获得这样结果的方法:

WITH 'cte1' AS (
...
),
WITH RECURSIVE 'cte2' AS (
...
),
WITH 'cte3' AS (
...
)
SELECT ... FROM 'cte3' WHERE ...

如您所见,我有一个递归CTE和两个非递归。

2 个答案:

答案 0 :(得分:52)

在顶部使用关键字WITH 一次。如果您的任何公用表表达式(CTE)是递归的(rCTE),您还必须在顶部一次添加关键字RECURSIVE,即使并非所有CTE都是递归的:

WITH RECURSIVE
  cte1 AS (...)         -- can still be non-recursive
, cte2 AS (SELECT ...
           UNION ALL
           SELECT ...)  -- recursive term
, cte3 AS (...)
SELECT ... FROM cte3 WHERE ...

The manual:

  

如果指定了RECURSIVE,则允许 SELECT子查询   按名称引用自己。

大胆强调我的。并且,更具洞察力:

  

RECURSIVE的另一个影响是WITH查询无需订购:   查询可以引用列表中稍后的另一个查询。 (然而,   循环引用或相互递归未实现。)   如果没有RECURSIVE,则WITH个查询只能引用同级WITH   WITH列表中较早的查询。

再次强调我的重点。意味着当使用WITH关键字时RECURSIVE子句的顺序无意义

顺便说一句,由于示例中的cte1cte2未在外部SELECT中引用,并且只是普通的SELECT命令(没有附带效果),因此它们永远不会已执行(除非在cte3中引用)。

答案 1 :(得分:16)

是。你不要重复WITH。你只需使用逗号:

WITH cte1 AS (
...
),
     cte2 AS (
...
),
     cte3 AS (
...
)
SELECT ... FROM 'cte3' WHERE ...

并且:仅对字符串和日期常量使用单引号。不要将它们用于列别名。无论如何,它们不被允许用于CTE名称。