PostgreSQL 嵌套 CTE 和 UNION
Posted
技术标签:
【中文标题】PostgreSQL 嵌套 CTE 和 UNION【英文标题】:PostgreSQL nested CTE and UNION 【发布时间】:2012-07-29 06:54:30 【问题描述】:我正在尝试使用 PostgreSQL 9.1.3 学习 SQL。我想了解一些让我觉得不一致的行为。也就是说:
这行得通:
WITH innermost AS (SELECT 2)
SELECT * FROM innermost
UNION SELECT 3;
我明白了:
?column?
----------
2
3
这行得通:
WITH outmost AS (
(WITH innermost AS (SELECT 2)
SELECT * FROM innermost)
)
SELECT * FROM outmost;
结果:
?column?
----------
2
这也有效:
WITH outmost AS (
SELECT 1
UNION (WITH innermost AS (SELECT 2)
SELECT * FROM innermost)
)
SELECT * FROM outmost;
我明白了:
?column?
----------
1
2
但这确实不起作用:
WITH outmost AS (
SELECT 1
UNION (WITH innermost as (SELECT 2)
SELECT * FROM innermost
UNION SELECT 3)
)
SELECT * FROM outmost;
结果:
ERROR: relation "innermost" does not exist
LINE 4: SELECT * FROM innermost
以我的思维方式,要么最后一个应该成功,要么其他一个应该失败。我没有看到模式。是否有一些通用规则可以让我预测嵌套 CTE 和 UNION 的哪些组合将起作用或不起作用?
【问题讨论】:
虽然您的最终查询看起来很尴尬,但应该没问题,恕我直言。这可能是解析器中的优先级/关联性错误。有一些语义限制(无嵌套递归 CTE,IIRC);也许解析器太挑剔了,或者太容易触发了。就个人而言,我使用了很多嵌套的 CTE(最多 4 层深),但我很少使用 UNION,除了在递归 CTE 中。 @AdamMackler 你应该把它作为你自己问题的答案 Tom Lane 承认您发现了一个错误,就像官方批准您提出了一个非常好的问题。请将您从列表中获得的内容发布为答案,并确保添加该主题的链接。 【参考方案1】:谜团解开了:我观察到的行为是一个已知的错误。我将相同的原始帖子发送到特定于 PostgreSQL 的列表并得到了这个答案:
这是一个错误:-(。解析分析代码似乎认为 WITH 只能附加到顶层或叶级 SELECT 内 设置操作树;但语法遵循 SQL 标准 说没有这样的话。 WITH 被接受,并附加到 中级 UNION 语法上应该去的地方, 然后在解析分析期间完全忽略它。会看到 修复它。
regards, tom lane
http://archives.postgresql.org/pgsql-novice/2012-07/msg00113.php
【讨论】:
似乎这已在 9.2 beta3 中修复。我引用时事通讯:* Fix WITH issue with set operations (UNION/INTERSECT/EXCEPT)
.
我刚刚安装了 9.2beta3,是的,我原来帖子中的非工作命令现在可以按预期工作。感谢您的提醒。
酷!感谢您跟踪此事!你的问题值得更多的赞成。 :) 顺便说一句,在这种情况下,我们鼓励您接受您自己的(正确)答案。以上是关于PostgreSQL 嵌套 CTE 和 UNION的主要内容,如果未能解决你的问题,请参考以下文章
如何在 postgres 中对相同的 CTE 表达式执行 UNION ALL?