数据导入:
Create table If Not Exists Employee (id int, name varchar(255), salary int, departmentId int);
Create table If Not Exists Department (id int, name varchar(255));
Truncate table Employee;
insert into Employee (id, name, salary, departmentId) values ('1', 'Joe', '70000', '1');
insert into Employee (id, name, salary, departmentId) values ('2', 'Jim', '90000', '1');
insert into Employee (id, name, salary, departmentId) values ('3', 'Henry', '80000', '2');
insert into Employee (id, name, salary, departmentId) values ('4', 'Sam', '60000', '2');
insert into Employee (id, name, salary, departmentId) values ('5', 'Max', '90000', '1');
Truncate table Department;
insert into Department (id, name) values ('1', 'IT');
insert into Department (id, name) values ('2', 'Sales');
表: Employee
+--------------+---------+
| 列名 | 类型 |
+--------------+---------+
| id | int |
| name | varchar |
| salary | int |
| departmentId | int |
+--------------+---------+
id是此表的主键列。
departmentId是Department表中ID的外键。
此表的每一行都表示员工的ID、姓名和工资。它还包含他们所在部门的ID。
表: Department
+-------------+---------+
| 列名 | 类型 |
+-------------+---------+
| id | int |
| name | varchar |
+-------------+---------+
id是此表的主键列。
此表的每一行都表示一个部门的ID及其名称。
编写SQL查询以查找每个部门中薪资最高的员工。
按 任意顺序 返回结果表。
查询结果格式如下例所示。
示例 1:
输入:
Employee 表:
+----+-------+--------+--------------+
| id | name | salary | departmentId |
+----+-------+--------+--------------+
| 1 | Joe | 70000 | 1 |
| 2 | Jim | 90000 | 1 |
| 3 | Henry | 80000 | 2 |
| 4 | Sam | 60000 | 2 |
| 5 | Max | 90000 | 1 |
+----+-------+--------+--------------+
Department 表:
+----+-------+
| id | name |
+----+-------+
| 1 | IT |
| 2 | Sales |
+----+-------+
输出:
+------------+----------+--------+
| Department | Employee | Salary |
+------------+----------+--------+
| IT | Jim | 90000 |
| Sales | Henry | 80000 |
| IT | Max | 90000 |
+------------+----------+--------+
解释:Max 和 Jim 在 IT 部门的工资都是最高的,Henry 在销售部的工资最高。
题解:
解题思路:
回忆一下 GROUP BY 语句
GROUP BY 字段名 # 根据字段进行分组
先对 DepartmentId 字段分组查询最大值,得到不同 DepartmentId 下的最大值
再根据 DepartmentId 字段连接 Department 表,根据 Salary 和 DepartmentId 查找 Department. Name 字段
解法一
先用子查询查到每个部门的最高工资,然后把用部门id把员工表和部门表关联在一起,最后用部门的最高工资做筛选,完整 sql 如下
select d.name Department, e.name as Employee, e.salary as Salary
from Employee e left join Department d on e.departmentId = d.id
where (departmentId, salary) in (
select departmentId, max(salary)
from Employee
group by departmentId
);
解法二
后来看网上说还有以另一种解法,觉得也挺巧妙,学习了。整体思路跟解法一相同,只是把两个字段的 in 操作换成了一个字段,把父子查询的部门id放在子查询作为筛选条件
select d.name Department, e.name as Employee, e.salary as Salary
from Employee e left join Department d on e.departmentId = d.id
where salary in (
select max(salary)
from Employee emp
where e.departmentId = emp.departmentId
);
解法三
我根据解法一和解法二想到了一种新的解法,把员工表部门最高薪资子查询结果作为临时表,加入到员工表跟部门表的关联中,形成三表连接,最后用临时表跟员工表的薪资比较就能得到结果了
select d.name Department, e.name as Employee, e.salary as Salary
from Employee e
left join Department d on e.departmentId = d.id
left join (
select departmentId, max(salary) as max_salary
from Employee emp
group by emp.departmentId
) as temp
on temp.departmentId = e.departmentId
where e.salary >= temp.max_salary;
三种算法效率比较
理论上应该是解法一跟解法三的效率差不多,且他们的效率高于解法二。因为解法一和解法三,子查询都只需要执行一次,但是解法二,每行员工表记录都需要关联执行一次子查询,所以效率可能不如其他两个。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/department-highest-salary
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。