PostgreSQL select 每个递归的最后一行

PostgreSQL select only last row from each recursion

让我们用以下 table 给出一个员工层次结构:

CREATE TABLE employee(
                        id serial PRIMARY KEY,
                        first_name varchar NOT NULL,
                        manager_id integer,
                        FOREIGN KEY(manager_id) REFERENCES employee(id)
                     );
INSERT INTO employee(first_name, manager_id)
              VALUES('Arden',          null),
                    ('Oliver',         null),
                    ('Luisa',          null),
                    ('Amelia',         null),
                    ('Olivia',         null),
                    ('Lily',              2),
                    ('Ava',               2),
                    ('Isabella',          2),
                    ('Charlie',           2),
                    ('Beatrice',          3),
                    ('Stephanie',         3),
                    ('Emily',             3),
                    ('Mila',              3),
                    ('Isla',              4),
                    ('Ashley',            4),
                    ('James',             7),
                    ('Jack',              7),
                    ('William',           8),
                    ('Harry',             8),
                    ('Robin',             8);

对于员工,例如id = 20,我们可以使用查询找到最高级别的经理:

WITH RECURSIVE cte AS
(
   SELECT
      0 cnt, id, first_name, manager_id
   FROM
      employee
   WHERE
      id = 20
   UNION ALL
   SELECT
      cnt+1, employee.id, employee.first_name, employee.manager_id
   FROM
      cte INNER JOIN employee ON cte.manager_id = employee.id
)SELECT * FROM cte WHERE cnt = (SELECT max(cnt) FROM cte);

但我需要获取整个员工列表 --- highest_level_manager 如下所示:

employee  |  highest_level_manager
----------------------------------
Robin     |    Oliver
Harry     |    Oliver
William   |    Oliver
Jack      |    Oliver
James     |    Oliver
Ashley    |    Amelia
Isla      |    Amelia
Mila      |    Luisa
Emili     |    Luisa
Stephanie |    Luisa
Beatrice  |    Luisa
Charlie   |    Oliver
Isabella  |    Oliver
Ava       |    Oliver
Lily      |    Oliver
Olivia    |    null
Amelia    |    null
Luisa     |    null
Oliver    |    null
Arden     |    null

有人知道怎么做吗?

为所有员工走树。将递归减少到 ids,在最终查询中添加名称:

with recursive cte as
(
    select
        id, manager_id, 0 as level
    from
        employee
    union all
    select
        c.id, e.manager_id, level+ 1
    from cte c
    join employee e on c.manager_id = e.id and e.manager_id is not null
)
select
    e.first_name as employee, 
    m.first_name as highest_level_manager
from (
    select distinct on(id) *
    from cte
    order by id desc, level desc
    ) c
join employee e on c.id = e.id
left join employee m on c.manager_id = m.id

Db<>fiddle.

中查看现场演示