PostgreSQL 12递归查询报[42P19]错误,求祖先后代关联实现方法
解决PostgreSQL递归查询中的"recursive reference must not appear more than once"错误
你的问题出在递归CTE的写法上——PostgreSQL不允许在递归成员中多次引用递归查询本身(也就是你的Ancestor CTE),而你的代码里把Ancestor自连接了,这违反了递归查询的核心规则。
正确的递归查询应该是迭代扩展祖先-后代链,而不是对整个结果集做笛卡尔积。我们只需要在递归部分,用当前递归结果里的descendant去关联原Parent表的parent,从而找到下一层的后代,以此延伸整个关系链。
正确的实现代码
WITH RECURSIVE Ancestor(ancestor, descendant) AS ( -- 锚点成员:获取所有直接的父子关系 SELECT parent, child FROM Parent UNION -- 递归成员:用已有的后代作为新的父节点,找到其对应的子节点,扩展祖先链 SELECT a.ancestor, p.child FROM Ancestor a JOIN Parent p ON a.descendant = p.parent ) SELECT * FROM Ancestor ORDER BY ancestor, descendant;
代码逻辑解释
- 锚点成员:先取出所有直接的父子对,也就是你期望结果里的前6行基础数据。
- 递归成员:每次从已有的
Ancestor结果中,把某个descendant(比如homer)作为父节点,去Parent表中找到它的子节点(bart、lisa),然后把原来的ancestor(比如abe)和新找到的子节点组合成新的行(abe | bart、abe | lisa);同理,当ancestor是ape,descendant是abe时,会找到abe的子节点homer,生成ape | homer,再进一步生成ape | bart、ape | lisa。
执行结果
运行这段代码后,你会得到完全符合你期望的结果:
ancestor | descendant ----------+------------ abe | bart abe | homer abe | lisa ape | abe ape | bart ape | homer ape | lisa homer | bart homer | lisa marge | bart marge | lisa
这样的写法只在递归成员中引用了一次Ancestor CTE,完全符合PostgreSQL的递归查询规则,而且不需要创建任何中间表就能得到所有的祖先-后代关系。
内容的提问来源于stack exchange,提问作者Tytire Recubans
相关产品推荐
相关产品推荐

