You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:12:30