# 部门工资最高的员工

  • 来源:力扣(LeetCode)
  • 链接:https://leetcode-cn.com/problems/department-highest-salary
  • 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

Employee 表包含所有员工信息,每个员工有其对应的 Id, salarydepartmentId

+----+-------+--------+--------------+
| Id | Name  | Salary | DepartmentId |
+----+-------+--------+--------------+
| 1  | Joe   | 70000  | 1            |
| 2  | Jim   | 90000  | 1            |
| 3  | Henry | 80000  | 2            |
| 4  | Sam   | 60000  | 2            |
| 5  | Max   | 90000  | 1            |
+----+-------+--------+--------------+
1
2
3
4
5
6
7
8
9

Department 表包含公司所有部门的信息。

+----+----------+
| Id | Name     |
+----+----------+
| 1  | IT       |
| 2  | Sales    |
+----+----------+
1
2
3
4
5
6

编写一个 SQL 查询,找出每个部门工资最高的员工。对于上述表,您的 SQL 查询应返回以下行(行的顺序无关紧要)。

+------------+----------+--------+
| Department | Employee | Salary |
+------------+----------+--------+
| IT         | Max      | 90000  |
| IT         | Jim      | 90000  |
| Sales      | Henry    | 80000  |
+------------+----------+--------+
1
2
3
4
5
6
7

解释:

MaxJimIT 部门的工资都是最高的,Henry 在销售部的工资最高。

# MySQL 8.0 窗口函数

SQL中我们经常遇到一种需求:分组排序分组求和等需求。要解决此类问题,最方便的就是使用窗口函数。

MySQL8.0开始支持窗口函数,这个功能在大多商业数据库和部分开源数据库中早已支持,有的也叫分析函数

什么叫窗口?

窗口的概念非常重要,它可以理解为记录集合,窗口函数也就是在满足某种条件的记录集合上执行的特殊函数。 对于每条记录都要在此窗口内执行函数,有的函数随着记录不同,窗口大小都是固定的,这种属于静态窗口; 有的函数则相反,不同的记录对应着不同的窗口,这种动态变化的窗口叫滑动窗口。

窗口函数和普通聚合函数也很容易混淆,二者区别如下:

  • 聚合函数是将多条记录聚合为一条;而窗口函数是每条记录都会执行,有几条记录执行完还是几条;
  • 聚合函数也可以用于窗口函数中;

按照功能划分,可以把MySQL支持的窗口函数分为如下几类:

  • 序号函数:row_number() / rank() / dense_rank()
  • 分布函数:percent_rank() / cume_dist()
  • 前后函数:lag() / lead()
  • 头尾函数:first_val() / last_val()
  • 其他函数:nth_value() / nfile()

序号函数的一般语法如下:

select 序号函数 over (partition by 用于分组的列名 order by 用于排序的列名)

其中,over是关键字,用来指定函数执行的窗口范围。

那么题解SQL如下:

select Department, Employee, Salary
from 
(
select 
    D.Name as Department, 
    E.Name as Employee, 
    E.Salary as Salary, 
    rank() over(partition by D.Name order by E.Salary desc) as rank_
from Employee E join Department D on E.DepartmentId = D.Id
) as tmp
where rank_ = 1
1
2
3
4
5
6
7
8
9
10
11

# MySQL 5.6/5.7 题解

SELECT
    Department.name AS 'Department',
    Employee.name AS 'Employee',
    Salary
FROM
    Employee
        JOIN
    Department ON Employee.DepartmentId = Department.Id
WHERE
    (Employee.DepartmentId , Salary) IN
    (   SELECT
            DepartmentId, MAX(Salary)
        FROM
            Employee
        GROUP BY DepartmentId
	)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

平时的IN都是一个字段的,其实也可以使用两个字段IN的,这是本题解的最大亮点。

WARNING

多字段IN的,一般的都会索引失效,平常少用!


参考文档

Last Updated: 3 years ago