MySQL基础之开窗函数

1. 聚合函数和开窗函数的区别

普通聚合函数(如 SUM(), AVG())是纵向聚合:一组数据聚合成一行然后拿到结果;

开窗函数是SQL中的一种横向分析函数,它不改变行数,而是为每一行计算一个基于该行所在分区中其他行的数据结果

例如:“统计每位员工的工资在其所在部门中的排名”。关键词就是“每”,要求每一行数据都要展示,而且是基于其所在部门的排名。

也就是说:

  • 每位员工都要保留在结果中(不能像普通聚合那样合并成一行);
  • 排名是相对于同一部门的其他员工
  • 需要考虑排序(工资越高,排名越靠前);

2. 开窗函数基本组成

函数名(字段参数) OVER (
  [PARTITION BY 分组字段] # 分区子句,开窗函数将在不同的分区内分别执行
  [ORDER BY 排序字段] # 排序子句
  [ROWS BETWEEN start AND end] # 窗口子句,通常用来作为滑动窗口使用
)

对于上面的窗口子句:

  • start的值一般为 1.unbounded preceding,边界是分区中的第一行 2.expr preceding,边界是当前行向上数expr
  • end的值一般为 1. unbounded following,边界是分区中最后一行 2.expr following,边界是当前行向下数expr
  • startend也可以是current row,边界是当前行
  • 默认为ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW

比如:

# 窗口范围是分区中的第一行到当前行
rows unbounded preceding 
# 窗口范围是当前行、当前行的前一行、当前行的后一行,一共三行记录。
rows between 1 preceding and 1 following

边界图如果所示:
在这里插入图片描述

3. 聚合开窗函数

基础数据:
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/ef57a5b9147440d4adfd136e736d0208.png

需求:统计每位员工从入职到现在,所在部门中总共发了多少钱工资。

SELECT *, 
sum(salary) over(PARTITION by part,username ORDER BY hire_date rows BETWEEN unbounded preceding and current row) as 'total_salary'
from employees

结果如下:
在这里插入图片描述

4. 排名开窗函数

统计每位员工在自己部门中的工资排名

4.1 RANK

特点:1. 相同值的行有相同排名 2. 跳过排名空行(看下面排名从1跳到了3)

SELECT *, RANK() over(PARTITION by part ORDER BY salary desc) as 'salary_rank'
from employees

在这里插入图片描述

4.2 DENSE_RANK

特点:1. 相同值的行有相同的排名 2. 不跳过排名空位(看下面排名1后面是2)

SELECT *, DENSE_RANK() over(PARTITION by part ORDER BY salary desc) as 'salary_rank'
from employees

在这里插入图片描述

4.3 ROW_NUMBER

特点:按原表数据的顺序,为每一行设置一个递增的数字

SELECT *, ROW_NUMBER() over(PARTITION by part ORDER BY salary desc) as 'salary_rank'
from employees

在这里插入图片描述

5. 取值开窗函数

5.1 FIRST_VALUE

需求:查看每位员工所在部门中工资最高的人的工资是多少(即第一名的工资)

SELECT *, FIRST_VALUE(salary) over(PARTITION by part ORDER BY salary desc ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as 'top_salary'
from employees

在这里插入图片描述

5.2 LAST_VALUE

需求:查看每位员工所在部门中工资低的人的工资是多少(即最后第一名的工资)

SELECT *, LAST_VALUE(salary) over(PARTITION by part ORDER BY salary desc ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as 'last_salary'
from employees

在这里插入图片描述

5.3 NTH_VALUE

需求:查看每位员工所在部门中工资排名第二的人的工资是多少

SELECT *, NTH_VALUE(salary, 2) over(PARTITION by part ORDER BY salary desc ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as 'nth_salary'
from employees

在这里插入图片描述

5.4 LAG

需求:查看每位员工所在部门中工资与上一个人的差值

SELECT *, salary - IFNULL(LAG(salary, 1) OVER (PARTITION BY part ORDER BY salary ASC), salary) AS diff_salary
FROM employees

在这里插入图片描述

5.5 LEAD

需求:判断每个员工工资是否高于下一位

SELECT *,
       CASE
         WHEN salary > LEAD(salary) OVER (PARTITION BY part) THEN '高于下一位'
         ELSE '不高于'
       END AS compare_salary
FROM employees

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值