MySQL窗口函数(排序函数)

MySQL窗口函数(排序函数)

文章目录

  • MySQL窗口函数(排序函数)
    • 1.常用的3种排序函数
    • 2.leetcode:184. 部门工资最高的员工

1.常用的3种排序函数

使用窗口函数,对查询结果进行排序,分配对应的编号

  • row_number()
  • rank()
  • dense_rank()
  • row_number()

    去重排序: 在每个分组内,为查询出来的每一行记录生成一个序号,依次排序且不会重复(即使结果相同,也会排出 1 2 3 名)

    +------------+----------+--------+--------+
    | Department | Employee | Salary | 编号    |
    +------------+----------+--------+--------+
    | IT         | Jim      | 90000  |  1     | 
    | IT         | Max      | 90000  |	2	  | 
    | IT         | li       | 90000  |	3	  | 
    | Sales      | Henry    | 80000  |	1	  |
    | Sales      | pan      | 95000  |	2	  |
    +------------+----------+--------+--------+
    
  • rank()

    跳跃排序: 在每个分组内,如果有两个第一位时,接下来就是第三位

    +------------+----------+--------+--------+
    | Department | Employee | Salary | Rank   |
    +------------+----------+--------+--------+
    | IT         | Jim      | 90000  |  1     | 
    | IT         | Max      | 90000  |	1	  | 
    | IT         | li       | 80000  |	3	  | 
    | Sales      | Henry    | 80000  |	1	  |
    | Sales      | pan      | 95000  |	2	  |
    +------------+----------+--------+--------+
    
  • dense_rank()

    连续排序,在每个分组内,如果有两个第一级时,接下来仍然是第二级。

    +------------+----------+--------+--------+
    | Department | Employee | Salary | Rank   |
    +------------+----------+--------+--------+
    | IT         | Jim      | 90000  |  1     | 
    | IT         | Max      | 90000  |	1	  | 
    | IT         | li       | 80000  |	2	  | 
    | Sales      | Henry    | 80000  |	1	  |
    | Sales      | pan      | 95000  |	2	  |
    +------------+----------+--------+--------+
    

语法:

 dense_rank() over(partition by 分组字段 order by 排序字段 desc) as '序号命名'

注意:

  • 使用row_number() over() 函数时,over()里的排序晚于where 、group by、order by的执行

  • partiton by 用于给结果集分组,如果未指定则将整个结果集作为一个分组

  • partiton by 与聚合函数区别:可以返回一个分组中多条记录,而聚合函数一般只有一个反应统计值的记录

举个栗子:

-- 表结构

-- 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            |
| 6  | li    | 90000  | 1            |
| 7  | pan   | 90000  | 2            |
+----+-------+--------+--------------+

-- Department 表:
+----+-------+
| id | name  |
+----+-------+
| 1  | IT    |
| 2  | Sales |
+----+-------+

-- sql语句:变动的是窗口函数(dense_rank()连续排序)
select 
    d.`name` Department, e.`name` Employee , e.salary Salary
from
    (select 
    id,`name`,salary,departmentId,
    dense_rank() over(partition by departmentId order by salary desc) as `Rank`
    from Employee
    ) e
    INNER JOIN 
    Department d on e.departmentId = d.ID
where e.Rank = 1

-- 执行结果(函数不同,结果集也不同)
+------------+----------+--------+--------+
| Department | Employee | Salary | Rank   |
+------------+----------+--------+--------+
| IT         | Jim      | 90000  |  1     | 
| IT         | Max      | 90000  |	1	  | 
| IT         | li       | 80000  |	2	  | 
| Sales      | pan      | 90000  |	1	  |
| Sales      | Henry    | 80000  |	2	  |
+------------+----------+--------+--------+

2.leetcode:184. 部门工资最高的员工

  1. SQL架构
Employee
+--------------+---------+
| 列名          | 类型    |
+--------------+---------+
| id           | int     |
| name         | varchar |
| salary       | int     |
| departmentId | int     |
+--------------+---------+
id是此表的主键列。
departmentId是Department表中ID的外键。
此表的每一行都表示员工的ID、姓名和工资。它还包含他们所在部门的ID。

Department
+-------------+---------+
| 列名         | 类型    |
+-------------+---------+
| id          | int     |
| name        | varchar |
+-------------+---------+
id是此表的主键列。
此表的每一行都表示一个部门的ID及其名称
  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 在销售部的工资最高。
  1. 建表语句
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');
insert into Employee (id, name, salary, departmentId) values ('6', 'li', '18000', '3');
Truncate table Department;
insert into Department (id, name) values ('1', 'IT');
insert into Department (id, name) values ('2', 'Sales');
  1. sql
-- 方法一:窗口函数的方式
select 
    d.`name` Department, e.`name` Employee , e.salary Salary
from
    (select 
    id,`name`,salary,departmentId,
    dense_rank() over(partition by departmentId order by salary desc) as `Rank`
    from Employee
    ) e
    INNER JOIN 
    Department d on e.departmentId = d.ID
where e.Rank = 1


-- 方法二:内连接+分组+聚合函数的方式
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
	)
;

-- 结果如下
+------------+----------+--------+--------+
| Department | Employee | Salary | Rank   |
+------------+----------+--------+--------+
| IT         | Jim      | 90000  |  1     |
| IT         | Max      | 90000  |	1	  |
| Sales      | Henry    | 80000  |	1	  |
+------------+----------+--------+--------+

注意: MySQL8.0以后的版本才支持窗口函数

你可能感兴趣的:(sql,java)