news 2026/9/13 3:10:17

MySQL 中的窗口函数

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MySQL 中的窗口函数

窗口函数是 MySQL 8.0 引入的一个重要特性,它可以在不改变数据行数的前提下,对每一行数据进行聚合、排名、累积等计算。与GROUP BY不同,窗口函数会保留所有原始行。

一、窗口函数

窗口函数的执行逻辑是:在每一行数据上,基于“窗口”(一个定义好的数据范围)进行计算,然后把计算结果的附加列(如排名、累计值等)直接写到对应的行上,不合并行。

语法结构

SELECT 列名, 窗口函数() OVER ( PARTITION BY 分区列 -- 分组 ORDER BY 排序列 -- 排序 ROWS/RANGE BETWEEN ... -- 窗口范围 ) AS 别名 FROM 表名;

二、窗口函数的三大类别

1. 排名函数

函数说明
ROW_NUMBER()按顺序编号,不处理并列(1,2,3,4...)
RANK()跳跃排名,并列后跳过(1,1,3,4...)
DENSE_RANK()连续排名,并列后不跳过(1,1,2,3...)
NTILE(n)将数据分成 n 组,返回组号
示例:按成绩排名
-- 创建示例表 CREATE TABLE students ( id INT, name VARCHAR(50), score INT, class VARCHAR(10) ); INSERT INTO students VALUES (1, 'Alice', 95, 'A'), (2, 'Bob', 85, 'A'), (3, 'Charlie', 95, 'A'), (4, 'David', 78, 'B'), (5, 'Eva', 92, 'B'), (6, 'Frank', 85, 'B'); -- 各排名函数的对比 SELECT name, score, ROW_NUMBER() OVER (ORDER BY score DESC) AS row_num, RANK() OVER (ORDER BY score DESC) AS rank, DENSE_RANK() OVER (ORDER BY score DESC) AS dense_rank, NTILE(3) OVER (ORDER BY score DESC) AS ntile FROM students;

结果

+---------+-------+---------+------+------------+-------+ | name | score | row_num | rank | dense_rank | ntile | +---------+-------+---------+------+------------+-------+ | Alice | 95 | 1 | 1 | 1 | 1 | | Charlie | 95 | 2 | 1 | 1 | 1 | | Eva | 92 | 3 | 3 | 2 | 2 | | Bob | 85 | 4 | 4 | 3 | 2 | | Frank | 85 | 5 | 4 | 3 | 3 | | David | 78 | 6 | 6 | 4 | 3 | +---------+-------+---------+------+------------+-------+

区别

  • ROW_NUMBER():1,2,3,4,5,6

  • RANK():1,1,3,4,4,6

  • DENSE_RANK():1,1,2,3,3,4

  • NTILE(3):1,1,2,2,3,3

2. 聚合函数(作为窗口函数)

函数说明
SUM()窗口内的累计和
AVG()窗口内的平均值
COUNT()窗口内的行数
MAX()/MIN()窗口内的最大值/最小值
示例:累计求和与移动平均
SELECT date, sales, SUM(sales) OVER (ORDER BY date) AS cumulative_sales, AVG(sales) OVER (ORDER BY date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg_3 FROM sales_data;

3. 取值函数

函数说明
LAG()获取当前行之前的第 N 行
LEAD()获取当前行之后的第 N 行
FIRST_VALUE()窗口内的第一行
LAST_VALUE()窗口内的最后一行
示例:计算环比增长率
SELECT month, revenue, LAG(revenue, 1) OVER (ORDER BY month) AS prev_month_revenue, ROUND( (revenue - LAG(revenue, 1) OVER (ORDER BY month)) / LAG(revenue, 1) OVER (ORDER BY month) * 100, 2 ) AS growth_rate_percent FROM monthly_revenue;

三、PARTITION BY(分组计算)

PARTITION BY将数据分组,窗口函数在每个分组内独立计算。

SELECT class, name, score, RANK() OVER (PARTITION BY class ORDER BY score DESC) AS rank_in_class FROM students;

结果

+-------+---------+-------+---------------+ | class | name | score | rank_in_class | +-------+---------+-------+---------------+ | A | Alice | 95 | 1 | | A | Charlie | 95 | 1 | | A | Bob | 85 | 3 | | B | Eva | 92 | 1 | | B | Frank | 85 | 2 | | B | David | 78 | 3 | +-------+---------+-------+---------------+

四、窗口范围(Frame)

窗口范围决定计算时包含哪些行:

写法说明
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW从开始到当前行(默认累计)
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW当前行及前 2 行
ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING前 1 行 + 当前行 + 后 1 行
ROWS UNBOUNDED PRECEDING从开始到当前行的简写
RANGE BETWEEN ...基于值的范围(而不是行数)
SELECT date, sales, SUM(sales) OVER (ORDER BY date) AS cumulative, -- 默认从开始到当前 SUM(sales) OVER (ORDER BY date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS last_3_days, SUM(sales) OVER (ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS total_all FROM sales_data;

五、窗口函数 vs GROUP BY

对比维度GROUP BY窗口函数OVER()
行数变化合并行,行数减少保持原行数
结果位置单独的结果行附加在原行旁边
子查询需求常需要子查询不需要
适用场景汇总统计排名、累计、移动平均
-- GROUP BY:只能看到汇总结果 SELECT department, AVG(salary) FROM employees GROUP BY department; -- 窗口函数:每行都保留,同时显示平均工资 SELECT employee_id, name, department, salary, AVG(salary) OVER (PARTITION BY department) AS dept_avg_salary FROM employees;
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 19:31:00

GLM付费首日DeepSeek重夺榜首,编程模型选型对比指南

GLM 付费首日,DeepSeek 重夺榜首。这个标题看起来像一场榜单排名的短期波动,但对经常折腾本地模型、API 接入和编码工具的开发者来说,它其实是两条产品路线之间的一次正面碰撞:一边是智谱 GLM 在编程场景快速发力,用 C…

作者头像 李华
网站建设 2026/9/13 3:08:43

Vibe Coding实战:一周5个项目烧掉100亿Token的经验总结

最近一段时间,Vibe Coding 几乎成了 AI 编程圈最热门的关键词。身边有朋友用它半天搓出一个工具站,也有团队拿它重写内部系统,但更多人是“烧了几百万 token 才发现代码根本没法上线”。我集中用 Vibe Coding 的方式做了一周实验,…

作者头像 李华
网站建设 2026/9/2 15:29:36

视频编解码算法工程师笔试核心解析:从率失真到RK3588硬件编解码

做了这么多年音视频技术,陆陆续续帮不少人复盘过各种厂子的编解码笔试。一个特别强烈的感受是:视频编解码算法工程师的笔试,和市面上绝大多数“算法工程师”岗位的笔试根本不在一个频道上。别人在刷LeetCode、追Transformer,你却在…

作者头像 李华
网站建设 2026/9/1 10:18:49

高频必考!滑动窗口最大值:单调队列如何把 O(nk) 优化到 O(n)?

LeetCode 239「滑动窗口最大值」,是Hard难度的经典题,也是各大厂面试的高频题。 给你一个数组和窗口大小k,窗口每滑一步,就要立刻知道窗口内的最大值。 暴力:每个窗口遍历一遍 → O(nk),n1e5 时直接炸大顶堆…

作者头像 李华
网站建设 2026/9/3 20:42:18

Grok 4.6 登陆 Azure AI Foundry:企业级模型部署与调用实战

当一条“Grok 4.6 登陆微软 Foundry 平台”的消息出现在信息流里,多数开发者的第一反应是:又多了一个模型入口。但如果你正在负责团队的 AI 基础设施选型,看到这条消息的感受会完全不同——这意味着你可以在企业已经使用的 Azure 生态里&…

作者头像 李华
网站建设 2026/9/2 16:12:43

基金定投助手:为什么你的基金定投总在追涨杀跌?价值平均法定投引擎 + 综合估值模型+动态再平衡仓位管理,一个单文件 HTML 的免费定投工具

这是一个真正能为你提升收益的工具 本文为推广下载介绍文章,工具免费开源,文末附下载方式。 一、先讲个真实痛点 你是否遇到过这种情况:每月定投日,打开 Excel,手工录入净值、翻公式算目标金额、再对照行情决定这期买…

作者头像 李华