如何用CTE获取PostgreSQL中ID的完整路径(剔除不完整路径)
解决方案
你的问题出在递归CTE的锚点选择上:原代码从NextID IS NULL的节点(路径终点)倒推,会生成所有中间路径。要只保留从无前置节点开始、到无后续节点结束的完整路径,需要调整递归方向,从「无前置的起点节点」开始正向遍历,最终筛选出路径终点的记录。
正确的递归CTE代码
WITH RECURSIVE path_cte AS ( -- 锚点:选取所有无前置ID的起点(ID不在任何NextID中) SELECT ID, NextID, ID::TEXT AS Path FROM t1 WHERE ID NOT IN (SELECT NextID FROM t1 WHERE NextID IS NOT NULL) UNION ALL -- 递归:从当前节点向下拼接路径 SELECT t1.ID, t1.NextID, cte.Path || ' --> ' || t1.NextID::TEXT FROM path_cte cte JOIN t1 ON cte.NextID = t1.ID ) -- 只保留路径终点(NextID为NULL)的记录,即为完整路径 SELECT Path FROM path_cte WHERE NextID IS NULL ORDER BY Path;
逻辑说明
- 锚点筛选:通过
ID NOT IN (SELECT NextID FROM t1 WHERE NextID IS NOT NULL)选出所有没有父节点的起点(比如你的数据中的1、2、3、4)。 - 正向递归:从起点开始,依次拼接后续节点的ID,生成完整的路径字符串。
- 终点筛选:最终只保留
NextID IS NULL的记录,这些就是从起点到终点的完整路径(包括单个节点的情况,比如ID=2)。
执行这段代码后,会得到你期望的结果:
1 --> 5 --> 8 2 3 --> 6 --> 9 --> 10 4 --> 7
内容的提问来源于stack exchange,提问作者lucky
相关产品推荐
相关产品推荐

