184:部门工资最高的员工
表: 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 在销售部的工资最高。
解题思路
首先Employee left join Department得到一个员工信息和部门信息关联的临时表。
然后group by DepartmentId分组,从每个组中找出max值。
错误示范1
select d.Name as Department, e.Name as Employee, max(Salary) as Salary
from Employee e left join Department d on e.DepartmentId = d.Id
group by e.DepartmentId;
上述代码错误的原因是,select中的max只挑选出了一个最大值,而忽略了可能有多个员工的薪资同为最大值的情况。
并且!select找出的max(Salary)并不是对应的行的Salary,而是整个组中的Salary。另外还存在的问题是,对于mysql 5.7及以上的版本,select的字段必须是被group by包含的字段,或是使用聚合函数。
错误示范2
select d.Name as Department, e.Name as Employee, Salary
from Employee e left join Department d on e.DepartmentId = d.Id
group by e.DepartmentId
having Salary = max(Salary);
上述代码看似解决了max只能去除最大值的问题,以及max(Salary)不是对应行的Salary的问题.
但是having子句中是不能出现非聚合函数中的属性名的,原因是group by分组之后得到的是组中的1条数据,所以having Salary只能获得这一条数据的Salary。
解决方法是不要在having子句中出现非聚合函数和非具体数据的其他字段。
解法一:子查询
首先找出每个分组及其最大值,然后判断表中每条数据的分组和Salary是否和这个相等。
select d.Name as Department, e.Name as Employee, Salary
from Employee e join Department d on e.DepartmentId = d.Id
where (e.DepartmentId, e.Salary) in (
select DepartmentId, max(Salary)
from Employee
group by DepartmentId
);
解法二:连接查询
Employee和查询出来的每个分组的最大值连接。
select d.Name as Department, e.Name as Employee, e.Salary
from Employee e join Department d on e.DepartmentId = d.Id join (
select DepartmentId, max(Salary) as Salary
from Employee
group by DepartmentId) t on e.DepartmentId = t.DepartmentId and e.Salary = t.Salary;
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/department-highest-salary
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。