Article / 文章
LeetCode 第181题:超过经理收入的员工
表:Employee +-------------+---------+ | Column Name | Type | +-------------+---------+ | id | int | | name | varchar | | salary | int | | managerId | int | +-------------+---------+
题目描述
表:Employee
+-------------+---------+
| Column Name | Type |
+-------------+---------+
| id | int |
| name | varchar |
| salary | int |
| managerId | int |
+-------------+---------+
id 是该表的主键。
该表的每一行都表示雇员的ID、姓名、工资和经理的ID。
编写一个SQL查询来查找收入比经理高的员工。
以任意顺序返回结果表。
难度
简单
题目链接
示例
示例:
输入:
Employee 表:
+----+-------+--------+-----------+
| id | name | salary | managerId |
+----+-------+--------+-----------+
| 1 | Joe | 70000 | 3 |
| 2 | Henry | 80000 | 4 |
| 3 | Sam | 60000 | Null |
| 4 | Max | 90000 | Null |
+----+-------+--------+-----------+
输出:
+----------+
| Employee |
+----------+
| Joe |
+----------+
解释: Joe 是唯一挣得比经理多的员工。
提示
- 每个员工的经理由 managerId 表示。
- 如果 managerId 为空,则该员工没有经理。
- 员工不能是自己的经理。
解题思路
方法一:自连接(Self Join)
这道题可以通过自连接来解决。我们可以将 Employee 表与自身连接,一个表示员工,另一个表示经理,然后比较员工的工资和经理的工资。
关键点:
- 使用 Employee 表自连接,通过 managerId 与经理的 id 进行匹配
- 筛选出员工工资大于经理工资的记录
- 选择员工的姓名作为结果输出
时间复杂度:O(n²),其中 n 是 Employee 表中的行数(自连接的时间复杂度) 空间复杂度:O(n)
方法二:子查询
另一种解决方法是使用子查询,通过嵌套查询来获取员工和其经理的工资,然后进行比较。
关键点:
- 对于每个员工,通过子查询获取其经理的工资
- 比较员工工资与经理工资
- 筛选出员工工资大于经理工资的记录
时间复杂度:O(n²),其中 n 是 Employee 表中的行数(嵌套查询的时间复杂度) 空间复杂度:O(n)
代码实现
SQL 实现(方法一:自连接)
SELECT e1.name AS Employee
FROM Employee e1
JOIN Employee e2 ON e1.managerId = e2.id
WHERE e1.salary > e2.salary;
SQL 实现(方法二:子查询)
SELECT name AS Employee
FROM Employee e1
WHERE salary > (
SELECT salary
FROM Employee e2
WHERE e2.id = e1.managerId
);
性能分析
各SQL实现的性能对比:
| 实现方法 | 执行用时 | 内存消耗 | 特点 |
|---|---|---|---|
| 方法一 | 422 ms | 0B | 使用JOIN,代码简洁清晰 |
| 方法二 | 637 ms | 0B | 使用子查询,直观但性能较差 |
补充说明
代码亮点
- 方法一使用自连接,代码简洁,SQL执行效率较高
- 方法二使用子查询,思路直观,容易理解
- 两种方法都考虑了 managerId 可能为 NULL 的情况
JOIN与子查询的比较
在SQL中,JOIN和子查询是两种常用的表连接方式,各有优缺点:
JOIN优势:
- 通常执行效率更高,特别是对于大型表
- 更灵活,可以同时连接多个表
- 代码通常更简洁
子查询优势:
- 直观,思路清晰
- 对于简单查询,编写可能更容易
- 在某些特定场景下更适用
对于本题,自连接(JOIN)通常是更好的选择,因为它执行效率更高,特别是当Employee表较大时。
常见错误
- 忘记处理 managerId 为 NULL 的情况
- 在子查询中引用外部查询的字段时出错
- 连接条件写错,导致匹配错误
- 没有正确理解自连接的概念,导致查询逻辑错误