SELECT查询,每行具有可变的列数

时间:2019-04-01 20:20:47

标签: mysql sql

我创建了一个员工表。这些员工中有一些向同一表中定义的其他员工报告。我们称他们为经理。

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我希望每行具有可变的列数,并且我不知道如何表达条件。

所需的输出: enter image description here

1 个答案:

答案 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     |          |          |