MySQL --- 窗口函数

目录

概念

语法

窗口确定

分组子句(partition by)

排序子句(order by)

窗口子句(rows)

总体流程

函数分类

排序类

案例

跨行类

案例

分组内topN

语法

案例


概念

窗口限定一个范围,它可以理解为满足某些条件的记录集合,窗口函数也就是在窗口范围内执行的函数。

语法

窗口函数有over关键字,指定函数执行的范围,可分为三部分:分组子句(partition by),排序子句(order by),窗口子句(rows)

<函数名> over (partition by <分组的列> order by <排序的列> rows between <起始行> and <终止行>)

TIP:Mysql8才支持窗口函数

窗口确定

分组子句(partition by)

不分组可以写成partition by null或者直接不写

后面可以跟多个列, 如 partition by cid, sname

TIP: 

partition by与group by的区别

1)前者不会压缩行数但是后者会

2)后者只能选取分组的列和聚合的列

也就是说group by 后生成的结果集与原表的行数和列数都不同

排序子句(order by)

不排序可以写成order by null 或者直接不写

asc或不写表示升序,desc表示降序

后面可以跟多个列, 如 order by cid, sname

窗口子句(rows)

窗口子句的描述:

起始行: N preceding/unbounded preceding

当前行: current row

 终止行: N following/unbounded following

TIP:

排序子句后面缺少窗口子句,窗口规范默认是 rows between unbounded preceding and current row

排序子句和窗口子句都缺失,窗口规范默认是 rows between unbounded preceding and unbounded following

总体流程

1.通过partition by 和 order by 子句确定大窗口( 定义出上界unbounded preceding和下界unbounded following)

2.通过row 子句针对每一行数据确定小窗口(滑动窗口)

3.对每行的小窗口内的数据执行函数并生成新的列

函数分类

排序类

函数名描述
RANK()分区中当前行的排名,带有间隙
DENSE_RANK()分区中当前行的排名,无间隙
ROW_NUMBER()其分区中的当前行数

案例

表图

代码

-- 【排序类】
-- 按班级分组后打上序号 不考虑并列
select *, row_number() over (partition by cid order by score desc) as '不可并列排名'
from SQL_5;
-- 按班级分组后作跳跃排名 考虑并列
select *, rank() over (partition by cid order by score desc) as '跳跃可并列排名'
from SQL_5;
-- 按班级分组后作连续排名 考虑并列
select *, dense_rank() over (partition by cid order by score desc) as '连续可并列排名'
from SQL_5;
-- 合并起来对比
select *,
       row_number() over (partition by cid order by score desc) as '不可并列排名',
       rank() over (partition by cid order by score desc)       as '跳跃可并列排名',
       dense_rank() over (partition by cid order by score desc) as '连续可并列排名'
from SQL_5;

结果

跨行类

函数名描述
LAG()分区内滞后当前行的参数值
LEAD()分区内当前行前导行的参数值

案例

 代码

-- 【跨行类】
-- lag/lead 函数 参数1:比较的列 参数2: 偏移量 参数3:找不到的默认值
-- 同一班级内,成绩比自己低一名的分数是多少
select *, lag(score, 1) over (partition by cid order by score) as '低一名的分数' from SQL_5;
-- 或者写成
select *, lag(score, 1, 0) over (partition by cid order by score) as '低一名的分数' from SQL_5;
-- 同一班级内,成绩比自己高2名的分数是多少
select *, lead(score, 2) over (partition by cid order by score) as '高两名的分数' from SQL_5;

结果

 

分组内topN

语法

select * from
(
	select *, row_number() over (partition by 分组列 order by 比较列) as rn from table
) as tmp
where rn <= N;

案例

表图

 代码

-- 【分组内topN】
-- 求出每个学生成绩最高的三条记录
select * from
(
    select *, row_number() over (partition by sname order by score desc) as rn from SQL_6
) temp
where rn <= 3

 结果

相关连接

聚合函数

常见函数

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值