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
中查看现场演示
让我们用以下 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
中查看现场演示