news 2026/8/21 4:16:40

MYSQL-窗口函数学习总结

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MYSQL-窗口函数学习总结

窗口函数不是将数据汇总成单个结果,而是为每一行数据都返回一个结果。

完整的窗口函数的定义:

window_function over(partition by...-- 分区参数 order by... -- 排序参数 frame_clause -- 窗口大小 );

以下代码所用数据集在之前的文章中可以找到。

select name , dept_id,sum(salary) over(partition by dept_id) from emp; select dept_id ,sum(salary) from emp group by dept_id; -- order by 用于指定分区内的数据的排序方式,作用类似于查询语句中的order by 子句。 select name ,salary, dept_id,sum(salary) over(partition by dept_id order by salary) from emp;

聚合窗口函数

移动平均值:avg 函数作为窗口函数使用时,可以用于计算随着当前行移动的窗口内数据行的平均值。例,查找不同产品截止每个月,最近三个月的平均销量。

create table sales_monthly( product varchar(10), ym int, amount int ); insert into sales_monthly values ('橘子',201801,10128),('橘子',201802,10221),('橘子',201803,10257),('橘子',201804,10386),('橘子',201805,11400),('橘子',201806,10566),('橘子',201807,10623),('橘子',201808,10697),('苹果',201801,10118),('苹果',201802,10211),('苹果',201803,10247),('苹果',201804,10286),('苹果',201805,11410),('苹果',201806,10565),('苹果',201807,10633),('苹果',201808,10687); select product as '产品', ym '年月', amount '销量', avg(amount) over (partition by product order by ym rows between 2 preceding and current row) as '平均销量 ' from sales_monthly order by product, ym; -- 当前平均值取的是当前日期和前两天的平均值。

也可更改为,当前日期为中间值

select product as '产品', ym '年月', amount '销量', avg(amount) over (partition by product order by ym rows between 1 preceding and 1 following) as '平均销量 ' from sales_monthly order by product, ym;
当不指定时,就是累计结果。
select product as '产品', ym '年月', amount '销量', avg(amount) over(partition by product order by ym) as '平均销量 ' from sales_monthly order by product,ym;

range关键字为单位指定窗口的偏移量。比如 查找短期内(5天)累计转账超过100万元的账号:

select log_ts,from_user,total_amount from ( select log_ts,from_user,sum(amount) over ( partition by from_user order by log_ts range interval '5' day preceding) as total_amount from transfer_log where type = '转账') t where total_amount >=1000000;

排名窗口函数

可以用来获取数据的分类排名。 常见的排名窗口函数如下:
row_number :函数可以为分区中的每行数据分配一个序列号,序列号从1开始。
rank :函数返回当前行在分区中的名次。如果存在名次相同的数据,后续的排名将会产生跳跃。
dense_rank: 函数返回当前行在分区中的名次。即使存在名次相同的数据,后续排名也是连续值。
percent_rank :函数以百分比的形式返回当前行在分区中的名次。如果存在名次相同的数据,后续的排名将会产生跳跃。
cume_dist :函数计算当前行在分区内的积累分布。
ntile:函数将分区内的数据分为N等分,并返回当前行所在分片的位置。
排名窗口函数不支持动态的窗口大小选项,而是以整个分区作为分析的窗口。

排名窗口函数不支持动态的窗口大小选项,而是以整个分区作为分析的窗口。

select name,dept_id,salary, row_number() over (partition by dept_id order by salary desc), rank() over (partition by dept_id order by salary desc), dense_rank() over (partition by dept_id order by salary desc), percent_rank() over (partition by dept_id order by salary desc) from emp; -- 可以用Window 封装 为 w window w as (partition by dept_id order by salary desc); (要在后面定义。) select name,dept_id,salary, row_number() over w, rank() over w, dense_rank() over w, percent_rank() over w from emp window w as (partition by dept_id order by salary desc);

cume_dist 函数返回当前行在分区内的累积分布,也就是排名在当前行之前(包含当前行)所有数据所占的比率,取值范围大于0且小于或等于1.

-- ;例如 查询返回所有员工按照月薪排名的累积分布情况: select name '姓名',salary, cume_dist() over( order by salary) '累计占比' from emp;

ntile 函数用于将分区内的数据分成N等分,并计算当前行所在的分片位置。

-- 例,以下语句将员工按照入职先后顺序分为5组,并计算每个员工所在的分组; select name '姓名',entrydate , ntile(5) over (order by entrydate) from emp;

取值窗口函数

lag函数返回窗口内当前行之前的第N行数据;
lead函数可以返回窗口内当前行之后的第N行数据。
first_value 返回窗口内第一行数据。
last_value 返回窗口内最后一行数据。

nth_value 返回窗口内第N行数据。

-- 案例分析:环比、同比分析 -- 环比是本期与上期数据相比的增长,例,产品6月的销量与五月的销量相比增加的部分; select product,ym,(amount-pre_amount)/pre_amount delta from( select * ,lag(amount,1) over (partition by product order by ym) pre_amount from sales_monthly) t; -- 同比增长 今年6月和 上一年6 月的销售相比增长的部分。lag(amount,12)当数据中每个月份的数据都有时,该字段表示当前月份之前第12期的销量,即去年同月份的销量 -- 复合增长率 每一期和第一期作比较

LAG(column, n, default_value)中的n表示向前第n行,default_value指定无数据时的默认值(如0或NULL)。

三类核心窗口函数对比

类别核心函数核心作用关键特点典型应用场景
聚合窗口函数SUM(),AVG(),COUNT(),MAX(),MIN()在窗口内进行聚合计算,不折叠行OVER()联用,将聚合结果“铺展”到每一行明细上。计算累计值、移动平均值、每组内占比。
排名窗口函数ROW_NUMBER(),RANK(),DENSE_RANK(),NTILE(n)为窗口内每一行生成序号或排名ORDER BY子句必不可少,决定了排序和排名依据。生成连续序号、并列排名、数据分箱(如分为上中下三组)。
取值窗口函数LAG(),LEAD(),FIRST_VALUE(),LAST_VALUE(),NTH_VALUE()访问窗口内其他行的值。实现了行与行之间的直接对话,是计算环比、同比的基础。

总结

  1. 灵魂在于OVER()子句:定义PARTITION BY(分组)和ORDER BY(排序)是写出正确窗口函数的关键。

  2. 性能关键:在PARTITION BYORDER BY涉及的列上建立索引,能极大提升执行效率。

  3. 组合使用:窗口函数可以组合。例如,可以先计算累计值(聚合函数),再对累计值进行排名。

    SELECT *, RANK() OVER (ORDER BY cumulative_amount DESC) FROM ( SELECT *, SUM(amount) OVER (PARTITION BY employee_id ORDER BY sale_date) AS cumulative_amount FROM sales ) t;
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/21 0:36:44

从 0 到 1 手写实现 MyBatis 框架:吃透 ORM 底层原理,面试不再慌

一、引言在Java后端开发领域,MyBatis作为一款轻量级ORM框架,凭借其灵活的SQL控制、较低的学习成本和出色的性能,成为了企业级开发中持久层的首选框架之一。大多数开发者都熟练使用MyBatis进行CRUD操作,但对其底层实现逻辑却一知半…

作者头像 李华
网站建设 2026/8/19 10:35:24

Wan2.2-T2V-5B如何实现动作流畅过渡?关键帧插值机制

Wan2.2-T2V-5B如何实现动作流畅过渡?关键帧插值机制 你有没有试过用AI生成一段“小狗跳跃接飞盘”的视频,结果画面像幻灯片一样一卡一卡的?🤯 就算模型能写出诗、画出画,一旦动起来——哎呀,“鬼手”乱飘、…

作者头像 李华
网站建设 2026/8/21 2:41:16

赋能文档的数字化智能处理:通用文字/文档/合同识别接口

在数字化转型的浪潮中,海量的纸质文档、图片信息如何快速、准确地转化为可编辑、可分析的结构化数据,是横亘在众多企业面前的效率壁垒。手动录入不仅耗时费力、错误率高,更无法适应现代业务对实时性与自动化处理的迫切需求。 通用文字识别AP…

作者头像 李华
网站建设 2026/8/21 16:02:37

深耕PCB十二年:高阶HDI板的工艺核心是什么

我是捷多邦的老张,深耕PCB十二年,如今谈起最先进的人工智能用高阶HDI板,最深的感触是:技术竞争早已从“毫米级”迈入“微米级”的精准对决。上个月的全球PCB技术展上,某企业展示的10阶HDI板样品,线宽线距仅…

作者头像 李华
网站建设 2026/8/21 1:50:22

10分钟精通Fooocus:零配置AI绘画从入门到专业创作

还在为复杂的AI绘画工具而头疼吗?想象一下,只需输入简单文字描述,就能在几分钟内获得媲美专业画师的作品。Fooocus正是这样一个革命性的AI图像生成平台,它将复杂的底层技术封装在简洁界面中,让每个人都能轻松驾驭AI创作…

作者头像 李华
网站建设 2026/8/21 3:34:39

Xray编辑器启动速度优化:从架构解析到实践指南

Xray编辑器启动速度优化:从架构解析到实践指南 【免费下载链接】xray An experimental next-generation Electron-based text editor 项目地址: https://gitcode.com/gh_mirrors/xray/xray Xray作为基于Electron的下一代实验性文本编辑器,其启动性…

作者头像 李华