题目描述

(通过次数145,057 | 提交次数288,684,通过率50.25%)

表: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 在销售部的工资最高。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/department-highest-salary
//测试数据
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));

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');

insert into Department (id, name) values ('1', 'IT');
insert into Department (id, name) values ('2', 'Sales');

解题思路

这是一个关于开窗函数的入门题。

可以说,** 对开窗函数掌握的熟练程度,是衡量一个数据人水平的分水岭 **。

在实际工作中,开窗函数也会经常使用到,对它们的区别及使用场景的考察,在面试和笔试的过程中经常会碰到,也是必须要掌握的。

我在面试的过程中,就经常会问到相关的问题。如果面试者答不上来,基本就被pass掉了。

一般来说,常用的开窗(分析)函数有如下3个:

** row_number **:为每一行返回一个唯一的数字,排名相等则按随机顺序返回排名。或者同时指定另一个字段,作为辅助排名的手段,以便在排名相等时,能够决定不同行的顺序。如:1,2,3,4,5。。。

** rank **:排名相等的情况下返回相同的排名,但排名结果会有断档。如:1,1,3,4,4,4,7,8,9。。。

** dense_rank **:排名相等的情况下返回相同的排名,但排名结果不会有断档。如:1,1,1,2,3,3,4,5,6,7,7,7,7,8,9。。。

因为本题要求,薪水相同的员工都需要返回,并且,只返回薪水最高的员工。那么,使用rank和dense_rank,都是可以满足本题要求的。

可以通过如下步骤,计算出题目要求的结果:

** 第一步 **:按部门开窗,算出每个部门每个人的薪水排名。薪水最高的排在第1位。

** 第二步 **:过滤出薪水排名为1的员工。

** 第三步 **:关联出部门的名称并返回。

参考SQL

未特别说明的情况下,参考SQL为基于MySQL8.0实现。
select
    c.name Department,
    b.name Employee,
    b.salary
from (
select
    a.name,a.salary,a.departmentId,
    rank() over(partition by a.departmentId order by a.salary desc) rk
from Employee a
)b
left join Department c
on b.departmentId = c.id
where b.rk = 1 ;
picture loss