如何使用 MySQL 和递归 CTE 显示所有加入给定经理的员工?

问题描述 投票:0回答:1

我需要能够展示每个员工如何在他们的各个领导层中发挥作用,而不仅仅是直接的亲子关系。换句话说,如果不包括 CEO 有 500 名员工,则 CEO 报告行将包含 500 行。

我见过类似的问题,请求是映射整个层次结构,而不是累积层次结构。

例如

EmployeeId, ManagerId, Name
1, NULL, TheGeneral
2, 1, Bob
3, 1, Christelle
4, 1, Wilfer
5, 2, Hailey
6, 2, George
7, 3, Mary
8, 4, Henry
9, 5, Wendy

我正在寻找的输出是

ReportIntoManagerId, ManagerialLevel, EmployeeId, Name
NULL, 1, 1, TheGeneral
1, 1, 2, Bob
1, 1, 3, Christelle
1, 1, 4, Wilfer
1, 1, 5, Hailey
1, 1, 6, George
1, 1, 7, Mary
1, 1, 8, Henry
1, 1, 9, Wendy
2, 2, 5, Hailey
2, 2, 6, George
2, 2, 9, Wendy 
3, 2, 3, Christelle
3, 2, 7, Mary
4, 2, 4, Henry
5, 3, 9, Wendy

但我不知道该怎么做。我知道它需要使用递归 CTE,但我不知道如何让它进行累积汇总。有人可以帮助我吗?

mysql common-table-expression recursive-query
1个回答
0
投票

我们可以使用递归 CTE 来获取每个员工的层次结构:

WITH RECURSIVE employee_paths (EmployeeId, name, path) AS
(
  SELECT EmployeeId, name, CAST(EmployeeId AS CHAR(200))
    FROM employees
    WHERE ManagerId IS NULL
  UNION ALL
  SELECT e.EmployeeId, e.name, CONCAT(ep.path, ',', e.EmployeeId)
    FROM employee_paths AS ep JOIN employees AS e
      ON ep.EmployeeId = e.ManagerId
)
SELECT * FROM employee_paths ORDER BY path;

结果:

EmployeeId  name        path
1           TheGeneral  1
2           Bob         1,2
5           Hailey      1,2,5
9           Wendy       1,2,5,9
6           George      1,2,6
3           Christelle  1,3
7           Mary        1,3,7
4           Wilfer      1,4
8           Henry       1,4,8

然后我们

JSON_TABLE
将逗号分隔的路径分成几行:

我们首先将字符串两边的方括号([])拼接成一个JSON数组。然后用

JSON_TABLE
转成表格

WITH RECURSIVE employee_paths (EmployeeId, name, path, level) AS
(
  SELECT EmployeeId, name, CAST(EmployeeId AS CHAR(200)), 1
    FROM employees
    WHERE ManagerId IS NULL
  UNION ALL
  SELECT e.EmployeeId, e.name, CONCAT(ep.path, ',', e.EmployeeId), level+1
    FROM employee_paths AS ep JOIN employees AS e
      ON ep.EmployeeId = e.ManagerId
)

SELECT j.ReportIntoManagerId, t2.level as ManagerialLevel, t.EmployeeId, t.name
FROM employee_paths t
CROSS JOIN JSON_TABLE(CONCAT('["', REPLACE(t.path, ',', '","'), '"]'),
                      '$[*]' COLUMNS (ReportIntoManagerId TEXT PATH '$')
                    ) j
INNER JOIN employee_paths t2 ON t2.EmployeeId = j.ReportIntoManagerId
WHERE j.ReportIntoManagerId <> t.EmployeeId OR t.EmployeeId = 1
order by ReportIntoManagerId

结果:

ReportIntoManagerId ManagerialLevel EmployeeId  name
1   1   1   TheGeneral
1   1   2   Bob
1   1   3   Christelle
1   1   4   Wilfer
1   1   5   Hailey
1   1   6   George
1   1   7   Mary
1   1   8   Henry
1   1   9   Wendy
2   2   5   Hailey
2   2   6   George
2   2   9   Wendy
3   2   7   Mary
4   2   8   Henry
5   3   9   Wendy

这里演示

© www.soinside.com 2019 - 2024. All rights reserved.