MySQL8.0新特性-窗口函数

简介

窗口函数与分组聚合函数类似,但是每行数据都生成一个结果。

聚合窗口函数: SUM、AVG、COUNT、MAX、MIN ……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-- 创建表
create table sales
(
year int,
country varchar(20),
goods varchar(50),
profit int
);
insert into sales values(2018,'c1','g1',314),(2016,'c1','g1',33),
(2017,'c1','g2',31),
(2016,'c2','g1',331),
(2017,'c2','g2',343),
(2018,'c2','g1',32),
(2016,'c3','g1',52),
(2017,'c3','g2',312),
(2018,'c3','g1',53);

普通函数

1
2
3
4
5
6
7
8
9
--正常情况下的计算不同国家的总利润:
select country,sum(profit) as all_profit
from sales group by country
order by country;
-- 分组聚合函数的写法,不需要手动分组
select year,country,goods,profit,
sum(profit) OVER (partition by country) as all_profit
from sales
order by country,year,goods,profit;

专用窗口函数

1
2
3
-- 准备数据
create table numbers(val int);
insert into numbers values(1),(2),(3),(3),(3),(3),(4),(5),(5),(6),(6),(7),(8),(8),(9);

序号函数

显示当前行号

  • ROW_NUMBER():排序
  • RANK()
  • DENSE_RANK()
1
2
3
4
5
6
-- 正常排序
select val,row_number() over (order by val) as 'row_number' from numbers;
-- 如果val相同,则排序相同,下一个排序号会出现间隙,步长不一定为1
select val,rank() over (order by val) as 'rank' from numbers;
-- 如果val相同,则排序相同,排序号之间没有间隙,步长为1
select val,dense_rank() over (order by val) as 'dense_rank' from numbers;

头尾\前后函数

  • FIRST_VALUE()
  • LAST_VALUE()
  • LEAD()
  • LAG()
1
2
3
4
5
select val,first_value(val) over (order by val) as 'first'
,last_value(val) over (order by val) as 'last'
,lead(val,1) over (order by val) as 'lead'
,lag(val,1) over (order by val) as 'lag'
from numbers;

分布函数

  • CUME_DIST()

    • 用途:分组内小于等于当前rank值的行数/分组内总行数,这个函数比percen_rank使用场景更多。
    • 应用场景:大于等于当前val的记录比例有多少。
  • PERCENT_RANK()

    • 用法:和之前的RANK()函数相关,每行按照如下公式进行计算: (rank - 1) / (rows - 1) 其中,rank为RANK()函数产生的序号,rows为当前窗口的记录总行数。
1
2
3
4
select val,rank() over (order by val) as 'rank'
,percent_rank() over (order by val) as 'percent_rank'
,cume_dist() over (order by val) as 'cume_dist'
from numbers;

数据区间函数

  • NTH_VALUE(expr,n)
    • 用途:返回窗口中第N个expr的值,expr可以是表达式,也可以是列名。
    • 应用场景:每个用户订单中显示本用户金额排名第二和第三的订单金额。
  • NTILE()
    • 用途:将分区中的有序数据分为n个桶,记录桶号。
    • 应用场景:将每个用户的订单按照订单金额分成3组。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
select year,profit,nth_value(profit,1)  over w as 'nth_1'
,nth_value(profit,2) over w as 'nth_2'
,nth_value(profit,3) over w as 'nth_3'
from sales
WINDOW w as (partition by year order by profit)
order by year,profit;

select year,profit,ntile(1) over w as 'ntile_1'
,ntile(2) over w as 'ntile_2'
,ntile(3) over w as 'ntile_3'
,ntile(5) over w as 'ntile_3'
from sales
WINDOW w as (partition by year order by profit)
order by year,profit;

本文地址:MySQL8.0新特性-窗口函数

推荐
MySQL8.0创建用户及其配置
MySQL8.0新特性-新的索引方式
MySQL8.0新特性-通用表表达式(CTE)
MySQL8.0新特性-窗口函数
MySQL8.0新特性-InnoDB增强
MySQL8.0新特性-JSON增强
官方介绍

本文地址: https://github.com/maxzhao-it/blog/post/33720/