PostgreSQL 9.6递归CTE查询层级数据:去重后仍存重复行
解决PostgreSQL递归查询中重复行问题:获取每个员工的最大层级记录
嘿,我明白你现在碰到的麻烦了——用WITH RECURSIVE查父子层级结构,想拿到每个员工对应最大层级的记录,加了DISTINCT还是有重复行,对吧?这其实是递归查询的特性导致的,我来给你拆解下怎么解决。
问题根源
递归遍历的时候,同一个员工节点可能会通过不同的父路径被多次命中,哪怕comp_user_id相同,只要其他字段(比如中间层级、路径信息)不一样,DISTINCT就会把这些行都保留下来。而你真正要的是每个员工对应最高层级的那条记录,所以核心不是去重,而是先计算层级,再筛选每个员工的最大层级条目。
解决方案代码
假设你的corp_companyuserprofile表有id(主键)、comp_user_id(员工ID)、parent_id(父节点ID,标识父子关系)这几个关键字段,我们可以这么写:
WITH RECURSIVE employee_hierarchy AS ( -- 锚点:取所有顶级节点(父节点为空的),层级设为0 SELECT comp_user_id, id, parent_id, 0 AS level FROM corp_companyuserprofile WHERE parent_id IS NULL UNION ALL -- 递归:遍历子节点,层级在父节点基础上加1 SELECT cu.comp_user_id, cu.id, cu.parent_id, eh.level + 1 AS level FROM corp_companyuserprofile cu JOIN employee_hierarchy eh ON cu.parent_id = eh.id ) -- 外层筛选:先按员工ID分组取最大层级,再关联回原递归结果拿完整记录 SELECT eh.* FROM employee_hierarchy eh INNER JOIN ( SELECT comp_user_id, MAX(level) AS max_level FROM employee_hierarchy GROUP BY comp_user_id ) max_level_data ON eh.comp_user_id = max_level_data.comp_user_id AND eh.level = max_level_data.max_level;
关键说明
- 层级计算:在递归CTE里明确给每个节点标记
level,顶级节点从0开始,子节点层级递加,这样我们能清晰知道每个节点在层级中的位置。 - 筛选最大层级:通过子查询分组计算每个
comp_user_id的最大层级,再和递归结果关联,就能精准拿到每个员工对应最高层级的那条记录,从根源避免重复。
如果你的表结构里父子关系的字段不是parent_id,只需要把代码里的关联条件改成你实际的字段就行~
内容的提问来源于stack exchange,提问作者Luke
相关产品推荐
相关产品推荐

