我创建了一个员工表。这些员工中有一些向同一表中定义的其他员工报告。我们称他们为经理。
CREATE TABLE employees (
id INT PRIMARY KEY,
name VARCHAR(255) NOT NULL UNIQUE,
managerID INT NULL,
FOREIGN KEY (managerID) REFERENCES employees (id) ON DELETE RESTRICT
) ENGINE=INNODB;
然后,在数据库中输入一些值:
INSERT INTO employees(id, name, managerID)
VALUES (1, "Ivan", NULL),
(2, "Peter", 1),
(3, "Alexandra", 1),
(4, "Maria", 2),
(5, "Marian", 2),
(6, "Margarita", 3),
(7, "Mihail", 3),
(8, "Eva", 6);
我想要一个SELECT
查询,该查询返回所有向其报告的员工和所有经理。现在,我拥有的下一个最好的东西是:
SELECT employee.name AS Name, manager.name AS `Reports to:`
FROM employees,
LEFT JOIN employees AS manager ON employee.managerID = manager.id;
具有可预测的输出:
Employee Reports to:
Ivan NULL
Peter Ivan
Alexandra Ivan
Maria Peter
Marian Peter
Margarita Alexandra
Mihail Alexandra
Eva Margarita
我想要的是一个这样的SELECT
查询,该查询将根据单个雇员有多少经理的事实返回可变数量的列。对我来说很明显,将需要递归SELF JOIN
,但是我不知道如何告诉DBMS我希望每行具有可变的列数,并且我不知道如何表达条件。
答案 0 :(得分:2)
我了解您想生成一个结果集,其中每条记录都对应一个雇员,并且其中的列显示该雇员的所有经理(该雇员的经理,然后是该经理的经理,等等)。
要记住的是,SQL查询必须返回一组固定的列。 RDBMS需要事先知道查询将返回多少列,以便能够解析并执行它。
这是一个可以处理多达5级管理的解决方案。它通过使用更多LEFT JOIN
扩展您的逻辑来起作用。它不漂亮,但是可以用。您可以添加mor联接来处理更多管理级别。
SELECT
e0.name AS Name,
e1.name AS Manager1,
e2.name AS Manager2,
e3.name AS Manager3,
e4.name AS Manager4,
e5.name AS Manager5
FROM employees e0
LEFT JOIN employees e1 ON e1.id = e0.managerID
LEFT JOIN employees e2 ON e2.id = e1.managerID
LEFT JOIN employees e3 ON e3.id = e2.managerID
LEFT JOIN employees e4 ON e4.id = e3.managerID
LEFT JOIN employees e5 ON e5.id = e5.managerID
在 this DB Fiddle 中包含示例数据,查询返回:
| Name | Manager1 | Manager2 | Manager3 | Manager4 | Manager5 |
| --------- | --------- | --------- | -------- | -------- | -------- |
| Ivan | | | | | |
| Peter | Ivan | | | | |
| Alexandra | Ivan | | | | |
| Maria | Peter | Ivan | | | |
| Marian | Peter | Ivan | | | |
| Margarita | Alexandra | Ivan | | | |
| Mihail | Alexandra | Ivan | | | |
| Eva | Margarita | Alexandra | Ivan | | |