窗口函数初识
窗口函数也叫OLAP函数(Online Anallytical Processing,联机分析处理),可以对数据进行实时分析处理。窗口函数和group by有类似之处,其区别在于窗口会对每个分组之后的数据进行分别操作,而group by一般对分组之后的函数使用聚集函数汇总。
窗口函数进阶
mysql 8.0 之后的版本开始支持窗口函数的功能,窗口函数一般用于实现排名和Top N的问题,下面用过leetcode的几个例子来说明一下,窗口函数的用法。
Leetcode 178 (Medium)成绩排名
这个题目需要实现对成绩的排名,并且有相同分数时排名相同,但不占用下一个同学的名次。考虑使用窗口函数dense_rank():
select score, dense_rank() over(order by score desc) as "Rank" from Scores;
Leetcode 184 (Medium)部门工资最高的员工
这个题目需要找出每个分组中的最大值,可以使用group by,但是我推荐使用窗口函数dense_rank():
select ed.Department, ed.Employee, ed.Salary from
(select d.Name as Department, e.Name as Employee, e.Salary,
dense_rank() over(partition by d.Name order by e.Salary desc) as ranking
from Employee as e inner join Department as d on e.DepartmentId = d.Id) as ed
where ed.ranking = 1 order by ed.Department;
除了使用排名函数dense_rank()以外,我们还使用分组操作partition by,在每个分组中构造排名,并通过where筛选。
Leetcode 185 (Hard)部门工资前三高的所有员工
这个题目是一个Top N的问题,这里的N为3,因此我们还是使用窗口函数分组并在上一题的基础上更改筛选条件:
select Department, Employee, Salary
from (select d.Name as Department,
e.Name as Employee,
e.Salary as Salary,
dense_rank() over(partition by d.Name order by e.Salary desc) as ranking
from Employee as e inner join Department as d on e.DepartmentId = d.Id) as ed
where ed.ranking <=3;