在使用数据库制作各种统计数据的时候,需要对数据进行排序,比如按照「分数、销量、人数」等数值进行排序,通常排序的方法有两种:
跳过之后的位次排序 不跳过之后的位次排序


窗口函数
窗口函数只在最新的MySQL
版本中才支持的!
窗口函数只在最新的MySQL
版本中才支持的!
窗口函数只在最新的MySQL
版本中才支持的!

参考资料:https://zhuanlan.zhihu.com/p/92654574
什么是窗口函数
窗口函数,也叫OLAP
函数(Online Anallytical Processing,联机分析处理),可以对数据库数据进行实时分析处理。
语法
窗口函数的基本语法:
<窗口函数> over (partition by <用于分组的字段名> -- partition子句可省略,不指定分组
order by <用于排序的列名>)复制
<窗口函数>
的位置上可以放两种函数:
专用窗口函数, rank、dense_rank、row_number
等聚合函数,如 sum、avg、count、max、min
等
因为窗口函数是对where
或者group by
子句处理后的结果进行操作,所以「窗口函数原则上只能写在select子句中」。
功能
同时具有分组和排序的功能 不改变原有表的行数 窗口函数原则上只能写在 select
子句中
实际场景
排名问题:每个部门按业绩来排名 topN
问题:找出每个部门排名前N
的员工进行奖励
rank/dense_rank/row_number
实例
rank
:并列跳跃排名dense_rank
:并列连续排名row_number
:连续排名
这3个函数的区别通过一个列子可以清楚地看到:

select
name,price,
rank() over (order by price desc) as rank_1,
dense_rank() (order by price desc) as rank_2,
row_number() (order by price desc) as rank_3
from products;复制
结论
name price rank_1 rank_2 rank_3
橘子 100 1 1 1
西瓜 80 2 2 2
苹果 50 3 3 3
香蕉 50 3 3 4
葡萄 50 3 3 5
柠檬 30 6 4 6复制
总结:
rank()
在出现了相同位次之后,跳过了相同的位次dense_rank()
则没有跳过相同的位次row_number()
按照自然数的顺序进行排列
❝在上述的这三个专用窗口函数中,函数后面的括号不需要任何参数,保持()空着就可以。
❞
知乎例子
实现rank()
select *,
rank() over (partition by 班级 -- 先分组
order by 成绩 desc) as ranking -- 再排序
from 班级表复制


不改变行数

非等值连接实现rank()
select p1.name,p1.price,
(select count(p2.price)
from products p2
where p2.price > p1.price) + 1
as rank_1
from products
order by rank_1;复制

子查询的功能是计算出比自己 (p1)
高的记录,并将其作为自己的位次比如对去重之后的价格 {100,80,50}
进行分析和排序,比100
大的个数是0,比80大的个数是1,比50大的个数是2+1
之后的排名实际上就是下面将会提到的dense_rank()
函数的排名
价格 | 排名 | +1 |
---|---|---|
100 | 0 | 1 |
80 | 1 | 2 |
50 | 2 | 3 |
「如果希望排序从0开始,则去掉加1」:

非等值连接实现dense_rank()
mysql> select p1.name, p1.price,
(select count(distinct p2.price) from products p2 where p2.price > p1.price) + 1 as rank_1
from products p1
order by rank_1;复制

使用变量实现row_number()
在MySQL5.7.28
中实现变量实现row_number
函数的功能
mysql> select p.name, p.price, (@pro_rank := @pro_rank + 1) row_Number
-> from products p,(select @pro_rank := 0) r
-> order by price desc;复制

如果是更高级的MySQL
版本,直接使用row_number()
函数实现
select name, price,
row_number() over (partition by name order by price desc) as rowNumber
from products复制
聚合函数作为窗口函数
聚合窗口函数和上面提到的专用窗口函数用法完全相同,只需要把「聚合函数」写在窗口函数的位置即可
「函数后面括号里面不能为空」 需要指定聚合的列名
需要在高级的MySQL
版本或者hive
中实现
mysql> select *,
-> sum(price) over (order by name) as rank_sum,
-> avg(price) over (order by name) as rank_avg,
-> max(price) over (order by name) as rank_max,
-> count(price) over (order by name) as rank_count
-> from products;复制
文章转载自尤而小屋,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
相关阅读
数据库国产化替代深化:DBA的机遇与挑战
代晓磊
1253次阅读
2025-04-27 16:53:22
2025年4月国产数据库中标情况一览:4个千万元级项目,GaussDB与OceanBase大放异彩!
通讯员
729次阅读
2025-04-30 15:24:06
国产数据库需要扩大场景覆盖面才能在竞争中更有优势
白鳝的洞穴
595次阅读
2025-04-14 09:40:20
【活动】分享你的压箱底干货文档,三篇解锁进阶奖励!
墨天轮编辑部
509次阅读
2025-04-17 17:02:24
一页概览:Oracle GoldenGate
甲骨文云技术
477次阅读
2025-04-30 12:17:56
GoldenDB数据库v7.2焕新发布,助力全行业数据库平滑替代
GoldenDB分布式数据库
471次阅读
2025-04-30 12:17:50
优炫数据库成功入围新疆维吾尔自治区行政事业单位数据库2025年框架协议采购!
优炫软件
361次阅读
2025-04-18 10:01:22
给准备学习国产数据库的朋友几点建议
白鳝的洞穴
291次阅读
2025-05-07 10:06:14
XCOPS广州站:从开源自研之争到AI驱动的下一代数据库架构探索
韩锋频道
278次阅读
2025-04-29 10:35:54
国产数据库图谱又上新|82篇精选内容全览达梦数据库
墨天轮编辑部
275次阅读
2025-04-23 12:04:21