目录
前言
一、窗口函数简介
窗口函数分类
语法结构
二、窗口函数运用展示
1.创建演示库
2.序号函数
1.ROW_NUMBER()函数
2.RANK()函数
3.DENSE_RANK()函数
3.分布函数
1.PERCENT_RANK()函数
2.CUME_DIST()函数
4.前后函数
1.LAG(expr,n)函数
2.LEAD(expr,n)函数
5.首尾函数
1.FIRST_VALUE(expr)函数
2. LAST_VALUE(expr)函数
6.其他函数
1.NTH_VALUE(expr,n)函数
2.NTILE(n)函数
点关注,防走丢,如有纰漏之处,请留言指教,非常感谢
参阅
MySQL从8.0版本开始支持窗口函数,其中,窗口可以理解为数据的集合。MySQL的开窗函数和Hive的开窗函数基本一致,窗口函数也就是在符合某种条件或者某些条件的记录集合中执行的函数,窗口函数会在每条记录上执行。一般我们在日常开发业务上面使用到开窗函数的场景都在聚合统计、数据挖掘之中,常用作聚合计算出某个特征数据。了解并掌握窗口函数将提升我们的数据挖掘能力。
该系列文章将按照这个脉络行文,此系列文章将被纳入我的专栏一文速学SQL各类数据库操作,基本覆盖到使用SQL处理日常业务以及常规的查询建库分析以及复杂操作方方面面的问题。从基础的建库建表逐步入门到处理各类数据库复杂操作,以及专业的SQL常用函数讲解都花费了大量时间和心思创作,如果大家有需要从事数据分析或者数据开发的朋友推荐订阅专栏,将在第一时间学习到最实用常用的知识。此篇博客篇幅较长,值得细读实践一番,我会将精华部分挑出细讲实践。博主会长期维护博文,有错误或者疑惑可以在评论区指出,感谢大家的支持。
窗口函数适用场景: 对分组统计结果中的每一条记录进行计算
的场景下, 使用窗口函数更好。
窗口函数(Window Function)可以像聚合函数一样对一组数据进行分析并返回结果,二者的不同之处在于,窗口函数不是将一组数据汇总成单个结果,而是为每一行数据都返回一个结果。聚合函数和窗口函数的区别如下图所示。
窗口函数可以分为静态窗口函数和动态窗口函数,其中,
窗口函数总体上可以分为序号函数、分布函数、前后函数、首尾函数和其他函数。
函数分类 | 函数 | 函数说明 |
序号函数 | row_number() | 顺序排列 |
rank() | 并列排序,会跳过重复的序号,比如序号为1、1、3 | |
dense_rank() | 并列排序,不会跳过重复的序号,比如序号为1,1,2 | |
分布函数 | percent_rank() | 等级值百分比 |
cume_dist() | 累积分布值 | |
前后函数 | lag(expr,n) | 返回当前行的前n行的expr的值 |
lead(expr,n) | 返回当前行的后n行的expr的值 | |
首尾函数 | first_value(expr) | 返回第一个expr的值 |
last_value(expr) | 返回最后一个expr的值 | |
其他函数 | nth_value(expr,n) | 返回第n个expr的值 |
ntile(n) | 将分区中的有序数据分为n个桶,记录桶的编号 |
窗口函数的语法结构形式:
OVER 关键字指定窗口的范围:
CREATE TABLE books_goods (
t_category_id int,
t_category VARCHAR(64),
t_name VARCHAR(64),
t_price FLOAT(32),
t_upper_time datetime
);
INSERT INTO books_goods (t_category_id, t_category, t_name, t_price,t_upper_time) VALUES
(1,'教育','计算机网络',40.0,'2020-11-10 00:00:00'),
(1,'教育','数据结构',58.0,'2020-11-10 00:00:00'),
(1,'教育','计算机系统',55.0,'2020-11-10 00:00:00'),
(2,'科幻','三体',30.0,'2020-11-10 00:00:00'),
(2,'科幻','流浪地球',35.0,'2020-11-10 00:00:00')
ROW_NUMBER()函数能够对数据中的序号进行顺序显示。
SELECT ROW_NUMBER() over(PARTITION by t_category_id ORDER BY t_price DESC) AS row_num,
t_category_id, t_category, t_name, t_price
FROM books_goods
这里如果我们插入一个相同数值的price:
INSERT INTO books_goods (t_category_id, t_category, t_name, t_price,t_upper_time) VALUES
(2,'科幻','死亡游戏',40.0,'2020-11-10 00:00:00');
INSERT INTO books_goods (t_category_id, t_category, t_name, t_price,t_upper_time) VALUES
(1,'教育','母猪的产后护理',40.0,'2020-11-10 00:00:00');
我们会发现价格相同的书籍但是序号确不一样,这时我们可以用RANK()函数处理。
使用RANK()函数能够对序号进行并列排序,并且会跳过重复的序号。
SELECT RANK() over(PARTITION by t_category_id ORDER BY t_price DESC) AS row_num,
t_category_id, t_category, t_name, t_price
FROM books_goods;
插入一条价格相同排第二的:
INSERT INTO books_goods (t_category_id, t_category, t_name, t_price,t_upper_time) VALUES
(1,'教育','软件工程导论',55.0,'2020-11-10 00:00:00');
可以看到,使用RANK()函数得出的序号为1、2、2、4、4,相同价格的商品序号相同,后面的商品序号是不连续的,跳过了重复的序号。
DENSE_RANK()函数对序号进行并列排序,并且不会跳过重复的序号,比如序号为1、1、2。
SELECT DENSE_RANK() over(PARTITION by t_category_id ORDER BY t_price DESC) AS row_num,
t_category_id, t_category, t_name, t_price
FROM books_goods;
可以看到,使用DENSE_RANK()函数得出的行号为1、2、2、3、3,相同价格的商品序号相同,后面的商品序号是连续的,并且没有跳过重复的序号。
PERCENT_RANK()函数是等级值百分比函数。按照如下方式进行计算:
(rank - 1) / (rows - 1)
其中,rank的值为使用RANK()函数产生的序号,rows的值为当前窗口的总记录数。
SELECT PERCENT_RANK() over(PARTITION by t_category_id ORDER BY t_price DESC) AS row_num,
t_category_id, t_category, t_name, t_price
FROM books_goods;
CUME_DIST()函数主要用于查询小于或等于某个值的比例。
row为当前值的行数,sum(row)分组内总行数。若两值相等则当前行数计算为最大行数:
SELECT CUME_DIST() over(PARTITION by t_category_id ORDER BY t_price DESC) AS rate,
t_category_id, t_category, t_name, t_price
FROM books_goods;
LAG(expr,n)函数返回当前行的前n行的expr的值。
例如,查询数据表中前一个商品价格与当前商品价格的差值。
SELECT t_category_id, t_name, t_price, pre_price,
t_price - pre_price AS diff_price
FROM (
SELECT t_category_id, t_name, t_price,
LAG(t_price,1) OVER w AS pre_price
FROM books_goods
WINDOW w AS (PARTITION BY t_category_id ORDER BY t_price)) t;
LEAD(expr,n)函数返回当前行的后n行的expr的值。
例如,查询数据表中后一个商品价格与当前商品价格的差值。
SELECT t_category_id, t_name, t_price, behind_price,
t_price - behind_price AS diff_price
FROM (
SELECT t_category_id, t_name, t_price,
LEAD(t_price,1) OVER w AS behind_price
FROM books_goods
WINDOW w AS (PARTITION BY t_category_id ORDER BY t_price)) t;
FIRST_VALUE(expr)函数返回第一个expr的值。
例如,按照价格排序,查询第1个商品的价格信息。
SELECT t_category_id, t_name, t_price,
FIRST_VALUE(t_price) OVER w AS first_price
FROM books_goods
WINDOW w AS (PARTITION BY t_category_id ORDER BY t_price);
LAST_VALUE(expr)函数返回最后一个expr的值。
例如,按照价格排序,查询最后一个商品的价格信息。
SELECT t_category_id, t_name, t_price,
LAST_VALUE(t_price) OVER w AS last_price
FROM books_goods
WINDOW w AS (PARTITION BY t_category_id ORDER BY t_price);
NTH_VALUE(expr,n)函数返回第n个expr的值。
查询数据表中排名第3和第4的价格信息。
SELECT t_category_id, t_name, t_price,
NTH_VALUE(t_price,2) OVER w AS second_price,
NTH_VALUE(t_price,3) OVER w AS third_price
FROM books_goods
WINDOW w AS (PARTITION BY t_category_id ORDER BY t_price);
该函数依赖row_number来排序。故存在价格相等但排序不重复的情况。
NTILE(n)函数将分区中的有序数据分为n个桶,记录桶编号。
例如,将表中的商品按照价格分为3组。
SELECT
NTILE(3) OVER w AS nt,
t_category_id, t_name, t_price
FROM books_goods
WINDOW w AS (PARTITION BY t_category_id ORDER BY t_price);
以上就是本期全部内容。我是fanstuck ,有问题大家随时留言讨论 ,我们下期见
SQL窗口函数_梁萌的博客-CSDN博客_sql窗口函数
窗口函数-内置函数-CSDNMySQL入门技能树数学