题目描述
(通过次数9,776 | 提交次数12,069,通过率81.00%)
+---------------+---------+
+---------------+---------+
| employee_name | varchar |
+---------------+---------+
这个表中每一行中,employee_id 表示职工的 ID,employee_name 表示职工的名字,manager_id 表示该职工汇报工作的直线经理。
这个公司 CEO 是 employee_id = 1 的人。
用 SQL 查询出所有直接或间接向公司 CEO 汇报工作的职工的 employee_id 。
由于公司规模较小,经理之间的间接关系不超过 3 个经理。
+-------------+---------------+------------+
| employee_id | employee_name | manager_id |
+-------------+---------------+------------+
+-------------+---------------+------------+
公司 CEO 的 employee_id 是 1.
employee_id 是 2 和 77 的职员直接汇报给公司 CEO。
employee_id 是 4 的职员间接汇报给公司 CEO 4 --> 2 --> 1 。
employee_id 是 7 的职员间接汇报给公司 CEO 7 --> 4 --> 2 --> 1 。
employee_id 是 3, 8 ,9 的职员不会直接或间接的汇报给公司 CEO。
链接:https://leetcode.cn/problems/all-people-report-to-the-given-manager
员工表:Employees
+---------------+---------+
| Column Name | Type |
+---------------+---------+
| employee_id | int |
| employee_name | varchar |
| manager_id | int |
+---------------+---------+
employee_id 是这个表的主键。
这个表中每一行中,employee_id 表示职工的 ID,employee_name 表示职工的名字,manager_id 表示该职工汇报工作的直线经理。
这个公司 CEO 是 employee_id = 1 的人。
用 SQL 查询出所有直接或间接向公司 CEO 汇报工作的职工的 employee_id 。
由于公司规模较小,经理之间的间接关系不超过 3 个经理。
可以以任何顺序返回无重复项的结果。
查询结果示例如下:
Employees table:
+-------------+---------------+------------+
| employee_id | employee_name | manager_id |
+-------------+---------------+------------+
| 1 | Boss | 1 |
| 3 | Alice | 3 |
| 2 | Bob | 1 |
| 4 | Daniel | 2 |
| 7 | Luis | 4 |
| 8 | Jhon | 3 |
| 9 | Angela | 8 |
| 77 | Robert | 1 |
+-------------+---------------+------------+
Result table:
+-------------+
| employee_id |
+-------------+
| 2 |
| 77 |
| 4 |
| 7 |
+-------------+
公司 CEO 的 employee_id 是 1.
employee_id 是 2 和 77 的职员直接汇报给公司 CEO。
employee_id 是 4 的职员间接汇报给公司 CEO 4 --> 2 --> 1 。
employee_id 是 7 的职员间接汇报给公司 CEO 7 --> 4 --> 2 --> 1 。
employee_id 是 3, 8 ,9 的职员不会直接或间接的汇报给公司 CEO。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/all-people-report-to-the-given-manager
员工表:Employees
+---------------+---------+
| Column Name | Type |
+---------------+---------+
| employee_id | int |
| employee_name | varchar |
| manager_id | int |
+---------------+---------+
employee_id 是这个表的主键。
这个表中每一行中,employee_id 表示职工的 ID,employee_name 表示职工的名字,manager_id 表示该职工汇报工作的直线经理。
这个公司 CEO 是 employee_id = 1 的人。
用 SQL 查询出所有直接或间接向公司 CEO 汇报工作的职工的 employee_id 。
由于公司规模较小,经理之间的间接关系不超过 3 个经理。
可以以任何顺序返回无重复项的结果。
查询结果示例如下:
Employees table:
+-------------+---------------+------------+
| employee_id | employee_name | manager_id |
+-------------+---------------+------------+
| 1 | Boss | 1 |
| 3 | Alice | 3 |
| 2 | Bob | 1 |
| 4 | Daniel | 2 |
| 7 | Luis | 4 |
| 8 | Jhon | 3 |
| 9 | Angela | 8 |
| 77 | Robert | 1 |
+-------------+---------------+------------+
Result table:
+-------------+
| employee_id |
+-------------+
| 2 |
| 77 |
| 4 |
| 7 |
+-------------+
公司 CEO 的 employee_id 是 1.
employee_id 是 2 和 77 的职员直接汇报给公司 CEO。
employee_id 是 4 的职员间接汇报给公司 CEO 4 --> 2 --> 1 。
employee_id 是 7 的职员间接汇报给公司 CEO 7 --> 4 --> 2 --> 1 。
employee_id 是 3, 8 ,9 的职员不会直接或间接的汇报给公司 CEO。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/all-people-report-to-the-given-manager
Create table If Not Exists Employees (employee_id int, employee_name varchar(30), manager_id int);
insert into Employees (employee_id, employee_name, manager_id) values ('1', 'Boss', '1');
insert into Employees (employee_id, employee_name, manager_id) values ('3', 'Alice', '3');
insert into Employees (employee_id, employee_name, manager_id) values ('2', 'Bob', '1');
insert into Employees (employee_id, employee_name, manager_id) values ('4', 'Daniel', '2');
insert into Employees (employee_id, employee_name, manager_id) values ('7', 'Luis', '4');
insert into Employees (employee_id, employee_name, manager_id) values ('8', 'John', '3');
insert into Employees (employee_id, employee_name, manager_id) values ('9', 'Angela', '8');
insert into Employees (employee_id, employee_name, manager_id) values ('77', 'Robert', '1');
//测试数据
Create table If Not Exists Employees (employee_id int, employee_name varchar(30), manager_id int);
insert into Employees (employee_id, employee_name, manager_id) values ('1', 'Boss', '1');
insert into Employees (employee_id, employee_name, manager_id) values ('3', 'Alice', '3');
insert into Employees (employee_id, employee_name, manager_id) values ('2', 'Bob', '1');
insert into Employees (employee_id, employee_name, manager_id) values ('4', 'Daniel', '2');
insert into Employees (employee_id, employee_name, manager_id) values ('7', 'Luis', '4');
insert into Employees (employee_id, employee_name, manager_id) values ('8', 'John', '3');
insert into Employees (employee_id, employee_name, manager_id) values ('9', 'Angela', '8');
insert into Employees (employee_id, employee_name, manager_id) values ('77', 'Robert', '1');
//测试数据
Create table If Not Exists Employees (employee_id int, employee_name varchar(30), manager_id int);
insert into Employees (employee_id, employee_name, manager_id) values ('1', 'Boss', '1');
insert into Employees (employee_id, employee_name, manager_id) values ('3', 'Alice', '3');
insert into Employees (employee_id, employee_name, manager_id) values ('2', 'Bob', '1');
insert into Employees (employee_id, employee_name, manager_id) values ('4', 'Daniel', '2');
insert into Employees (employee_id, employee_name, manager_id) values ('7', 'Luis', '4');
insert into Employees (employee_id, employee_name, manager_id) values ('8', 'John', '3');
insert into Employees (employee_id, employee_name, manager_id) values ('9', 'Angela', '8');
insert into Employees (employee_id, employee_name, manager_id) values ('77', 'Robert', '1');
解题思路
题目要求从CEO(employee_id = 1)出发,找出直接下属,以及下属的下属,下属的下属的下属。
因为题目中已经说明公司层级不高,最高3级。那么可以通过穷举的方式来实现。
也就是说,**第一步**:找到CEO的直接下属;
**第二步**:找到下属的下属;
**第三步**:找到下属的下属的下属;
说起来比较拗口,但思路就是这样。如果层级更深,就继续向下查。
最后一步:合并上面3步找到的所有人,然后去重即可。
上面这种方法,SQL写起来比较简单。但仅仅针对层级不深的情况比较适用。
如果层级比较深,这种方法就显得非常臃肿。
显然,递归是一个比较好的方法。
在推文单挑力扣(LeetCode)SQL题:1613. 找到遗失的ID(难度:中等)中,我介绍了几种不同数据库实现递归的方法。
今天主要介绍下Oracle数据库中使用connect by实现递归的方法。
Oracle中,使用connect by实现递归的语法如下:
connect by [nocycle] [prior] id=parentid
select *
from table
[start with condition]
connect by [nocycle] [prior] id=parentid
select *
from table
[start with condition]
connect by [nocycle] [prior] id=parentid
其中,start with condition是用来限制取出第一层数据的条件;
id = parentid是用来从第一层数据出发,查出下一层次的数据的条件。
当prior的位置不变,后面条件为id = parentid时,表示从根节点出发,查出以下所有层级的节点;
当prior的位置不变,后面条件为parentid = id时,表示从叶子节点出发,查出以上所有层级的节点;
当然,也可以条件不变,改变prior关键字的位置,可以实现同样的效果。
参考SQL
未特别说明的情况下,参考SQL为基于MySQL8.0实现。
start with a.manager_id = 1
connect by nocycle prior a.employee_id = a.manager_id
select a.employee_id
from employees a
where a.employee_id <> 1
start with a.manager_id = 1
connect by nocycle prior a.employee_id = a.manager_id
group by a.employee_id;
select a.employee_id
from employees a
where a.employee_id <> 1
start with a.manager_id = 1
connect by nocycle prior a.employee_id = a.manager_id
group by a.employee_id;