mysql 窗口函数_mysql窗口函数小结

a8c5497fd0d10ab9cbd98c5c87d43d50.png

MySQL8.0开始支持窗口函数,其他一些商业或开源数据库早已支持窗口函数,如Oracle、DB2、 PostgreSQL、SQL Server等。所谓窗口函数,是指对查询的每一行,利用和这一行相关的行构成一 个窗口,对这个窗口进行计算,得到一个值作为结果。

3af50b40d871f749ac68be02708ecdfb.png

窗口函数的基本用法:

函数名 OVER 子句

over关键字用来指定函数执行的窗口范围,若后面括号中什么都不写,则意味着窗口包含满足WHERE条件的所有行,窗口函数基于所有行进行计算;如果不为空,则支持以下4中语法来设置窗口范围。①window_name:给窗口指定一个别名。如果SQL中涉及的窗口较多,采用别名可以看起来更清晰易读;②PARTITION BY 子句:窗口按照某些字段进行分组,窗口函数在不同的分组上分别执行;③ORDER BY子句:按照某些字段进行排序,窗口函数将按照排序后的记录顺序进行编号;④FRAME子句:FRAME是当前分区的一个子集,子句用来定义子集的规则,通常用来作为滑动窗口使用。

窗口函数与聚合函数的区别

1.聚合函数是将多条记录聚合为一条;而窗口函数是每条记录都会执行,有几条记录执行完还是几条。

2. 对于聚合函数来说,不能将聚合前后的数据展示在一起,而窗口函数就可以做到这一点。

3.聚合函数也可以用作窗口函数

按照功能划分,可以把MySQL支持的非聚合窗口函数分为4类。

67f1b3b77ddcbb915064eae76fc8e52f.png

新增测试数据:

CREATE 

排序函数

row_number:计算当前行在分区中的序号

按照科目进行分组,并给每一条数据都加上行号

SELECT name,sub,grade , row_number() OVER (PARTITION BY sub ORDER BY grade DESC ) 
 AS grade_order  FROM stu_grade_info;

e8ad039bf83ce8cbda3d6b1325dd4085.png

rank:计算当前行在分区中的排名,有间隔

按照科目进行分组,将学生对应分数的由高到底排列有间隙排列,

SELECT name,sub,grade , rank() OVER (PARTITION BY sub ORDER BY grade DESC ) 
  AS grade_order FROM stu_grade_info

2b6ae5035ee56be167df83f3e38b1c78.png

dense_rank:计算当前行在分区中的排名,无间隔

按照科目进行分组,将学生对应分数的由高到底排列无间隙排列

SELECT 

41fb47cdfbf64f4f9153e64b248f2f12.png

重复使用的窗口使用window语句命名。

SELECT name,sub,grade , rank() OVER w AS grade_order_rk,  dense_rank() OVER w 
  AS grade_order_drk  FROM stu_grade_info  
  WINDOW w AS (PARTITION BY sub ORDER BY grade DESC );

38f7bdb0a5e6c8bd8cdea55635f4cf0a.png

分布函数:

percent_rank

1.计算给定行的百分比排名 计算结果:(相对位置-1)/(总行数-1)];

2.对于重复值取第一行

3.计算结果:(rank - 1) / (rows - 1)

cume_dist

1.计算某个值在一组有序的数据中累计的分布值

2.计算结果:相对位置/总行数,返回值为(0,1];

3.对于重复值取最后一行

查看分数所占的百分比和累积分布值

select name,sub,grade,percent_rank() over(partition by sub order by grade desc) 
  as 'percent_rank',cume_dist() over(partition by sub order by grade desc) 
  as 'cume_dist' from stu_grade_info;

3d54a5077cab1d864afcfef545719626.png

偏移函数:

插入数据:

create table sql27_car_sale(
	id int not null auto_increment primary key,
	name varchar(30) not null comment '名称',
	month varchar(7) comment '月份',
	volume int comment '销量'
)engine=InnoDB;
insert into sql27_car_sale(name, month, volume) values('大众朗逸', '2018-01', 44202);
insert into sql27_car_sale(name, month, volume) values('大众朗逸', '2018-02', 25460);
insert into sql27_car_sale(name, month, volume) values('大众朗逸', '2018-03', 38914);
insert into sql27_car_sale(name, month, volume) values('大众朗逸', '2018-04', 30449);
insert into sql27_car_sale(name, month, volume) values('大众朗逸', '2018-05', 40570);
insert into sql27_car_sale(name, month, volume) values('大众朗逸', '2018-06', 41653);
insert into sql27_car_sale(name, month, volume) values('大众朗逸', '2018-07', 33484);
insert into sql27_car_sale(name, month, volume) values('大众朗逸', '2018-08', 38946);
insert into sql27_car_sale(name, month, volume) values('大众朗逸', '2018-09', 44579);
insert into sql27_car_sale(name, month, volume) values('大众朗逸', '2018-10', 43974);
insert into sql27_car_sale(name, month, volume) values('大众朗逸', '2018-11', 46241);
insert into sql27_car_sale(name, month, volume) values('大众朗逸', '2018-12', 40484);
insert into sql27_car_sale(name, month, volume) values('大众朗逸', '2019-01', 59507);
insert into sql27_car_sale(name, month, volume) values('大众朗逸', '2019-02', 34379);
insert into sql27_car_sale(name, month, volume) values('大众朗逸', '2019-03', 49762);
insert into sql27_car_sale(name, month, volume) values('大众朗逸', '2019-04', 30739);
insert into sql27_car_sale(name, month, volume) values('大众朗逸', '2019-05', 35752);
insert into sql27_car_sale(name, month, volume) values('大众朗逸', '2019-06', 34330);
insert into sql27_car_sale(name, month, volume) values('大众朗逸', '2019-07', 36921);
insert into sql27_car_sale(name, month, volume) values('大众朗逸', '2019-08', 32135);
insert into sql27_car_sale(name, month, volume) values('大众朗逸', '2019-09', 48546);
insert into sql27_car_sale(name, month, volume) values('大众朗逸', '2019-10', 40608);
insert into sql27_car_sale(name, month, volume) values('大众朗逸', '2019-11', 52691);
insert into sql27_car_sale(name, month, volume) values('大众朗逸', '2019-12', 65138);
insert into sql27_car_sale(name, month, volume) values('大众朗逸', '2020-01', 35898);
insert into sql27_car_sale(name, month, volume) values('大众朗逸', '2020-02', 3303 );
insert into sql27_car_sale(name, month, volume) values('大众朗逸', '2020-03', 24698);

计算大众朗逸汽车销量的同比、环比。

SELECT
	Z.MONTH,
	Z.volume,
	Z.last_volume,
	ifnull(( Z.volume - Z.last_volume )/ Z.last_volume * 100, 0 ) AS mm,
	Z.last_year_volume,
	ifnull(( Z.volume - Z.last_year_volume )/ Z.last_year_volume * 100, 0 ) AS yy 
FROM
	(	SELECT NAME,MONTH,volume,
		lag( volume, 1, 0 ) over ( ORDER BY MONTH ASC ) AS last_volume,
		lag( volume, 12, 0 ) over ( ORDER BY MONTH ASC ) AS last_year_volume 
	FROM sql27_car_sale  
	) AS Z;

b4153e1c2e15dbdb82f1a8071c330c4a.png

分组函数:

ntile函数的说明

1. ntile(n)表示将数据分为n组,组的编号范围1-n。

2. 如果分区中的总记录数能被n整除,则每组的记录的相等(平分)。

3. 如果分区中的总记录数不能被n整除,每组的记录数相差为1。

将大众朗逸汽车的销量数据分成5组,并显示每行数据的所属组编号。

select name,month,volume,ntile(5) over(order by volume desc) as 'ntile'
from sql27_car_sale

6b0f0257464500f4f0e6127fbad12601.png

聚合参数:

将学生成绩按照课程分组,列出每科最高分,最低分,平均分

select name,sub,grade,  max(grade) over w grade_max,	min(grade) over w grade_min,
AVG(grade) over w grade_avg from stu_grade_info window w as(PARTITION  by sub )

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值