MySQL 窗口函数

聚合函数作为窗口函数

设聚合函数为op语法结构:

op(字段名A) over(partition by 字段名B order by 字段名C rows between D1 and D2)

其中:

  • partition by:按照某一字段将数据进行分组

  • order by:按照某一字段将数据进行排序,默认升序ASC,可设置为降序DESC

  • 字段名A:执行聚合操作的字段

  • 字段名B:通过该字段进行分组

  • 字段名C:通过该字段进行排序

  • D1:行数的起始范围

  • D2:行数的结束范围

其中表示范围的D1和D2可以用下图这些表示方法:

若没有字段名C rows between D1 and D2,默认范围为rows between unbounded preceding and current row,即范围为之前所有的行和本行。一个例子如下:

sql 复制代码
Create table If Not Exists tb(id int, gid int,val int);
insert into tb values (1, 1, 1);
insert into tb values (2, 2, 2);
insert into tb values (3, 1, 3);
insert into tb values (4, 2, 4);
insert into tb values (5, 1, 3);
insert into tb values (6, 2, 6);
insert into tb values (7, 1, 7);
insert into tb values (8, 2, 8);
insert into tb values (9, 1, 9);

select id, gid, val, sum(val) over(partition by gid order by id) as sum, avg(val) over(partition by gid order by id) as avg
from tb;

执行结果:

可以看出,这里的sum窗口函数即按gid分组,并在组内按id排序,返回每行val上的前缀和,avg类似。


分区排序函数

设聚合函数为op语法结构:

op(字段名A) over(partition by 字段名B order by 字段名C)

示例如下:

sql 复制代码
Create table If Not Exists tb(id int, gid int,val int);
insert into tb values (1, 1, 1);
insert into tb values (2, 2, 2);
insert into tb values (3, 1, 3);
insert into tb values (4, 2, 4);
insert into tb values (5, 1, 3);
insert into tb values (6, 2, 6);
insert into tb values (7, 1, 7);
insert into tb values (8, 2, 8);
insert into tb values (9, 1, 9);

select id, gid, val, rank() over(partition by gid order by val) as rank_, row_number() over(partition by gid order by val) as row_num,  dense_rank() over(partition by gid order by val) as drank
from tb
where gid = 1;

执行结果:

三种函数的特点简单地说:

  • rank():序号可以重复,可能不连续
  • row_number():序号不能重复,连续
  • dense_rank(): 序号可以重复,连续

分区按数量分组函数

分区按数量分组函数ntile语法结构:

ntile(k) over(partition by 字段名A order by 字段名B)

其中k为组数,设partition by 划分的一个区域的行数为n,则这个区域的前 n % k n\%k n%k组中每组行数为 ⌈ n / k ⌉ \left \lceil n/k \right \rceil ⌈n/k⌉、这个区域后 n − n % k n-n\%k n−n%k组中每组行数为 ⌊ n / k ⌋ \left \lfloor n/k \right \rfloor ⌊n/k⌋。一个例子如下:

sql 复制代码
Create table If Not Exists tb(id int, gid int,val int);
insert into tb values (1, 1, 1);
insert into tb values (2, 2, 2);
insert into tb values (3, 1, 3);
insert into tb values (4, 2, 4);
insert into tb values (5, 1, 3);
insert into tb values (6, 2, 6);
insert into tb values (7, 1, 7);
insert into tb values (8, 2, 8);
insert into tb values (9, 1, 9);

select id, gid, ntile(3) over(partition by gid order by id) as ind
from tb;

执行结果:

可以看出gid为1的区域中分为三组(ind范围为1~3),前两组的行数为2,剩余一组的行数为1。


参考:

https://zhuanlan.zhihu.com/p/366553723?utm_id=0

https://www.mysqltutorial.org/mysql-window-functions/

相关推荐
xhbh6666 分钟前
【实战避坑】MySQL自增主键(AUTO_INCREMENT)全解:从锁机制、间隙问题到分库分表替代方案
android·数据库·mysql·mysql自增主键
hh真是个慢性子20 分钟前
mongodb慢查询优化 速度欻欻滴~
数据库·mongodb·性能优化·慢查询
色空大师28 分钟前
【MongoDB的RLE压缩数据存储】
数据库·mongodb
安当加密28 分钟前
通过TDE透明加密实现人大金仓数据库的免改造存储加密方案
数据库·金仓·透明加密
养生技术人30 分钟前
Oracle OCP认证考试题目详解082系列第49题
运维·数据库·sql·oracle·database·开闭原则·ocp
white-persist40 分钟前
SQL 注入详解:从原理到实战
前端·网络·数据库·sql·安全·web安全·原型模式
Databend1 小时前
Raft 中的 IO 执行顺序:内存状态与持久化状态的陷阱
数据库
兜兜风d'2 小时前
redis字符串命令
数据库·redis·缓存
忧郁的蛋~3 小时前
EFcore查询a表中符合b表列的值
数据库
xwz小王子3 小时前
ManipulationNet:开启真实世界机器人操作基准测试新时代
数据库·机器人