MySQL 窗口函数详解

很多人第一次看到窗口函数的时候,都会觉得:

sql 复制代码
这是什么东西?

尤其是:

sql 复制代码
OVER()
ROW_NUMBER()
RANK()

看起来特别抽象。

但实际上:

窗口函数本质上就是"在保留原数据的基础上做统计"。

这是它和:

sql 复制代码
GROUP BY

最大的区别。


一、先理解什么是窗口函数

先看一个普通需求。

比如有一张成绩表:

id name score
1 张三 90
2 李四 85
3 王五 95

现在需求:

查询:

  • 学生姓名
  • 分数
  • 排名

这时候:

sql 复制代码
GROUP BY

其实做不了。

因为:

sql 复制代码
GROUP BY

会把原数据"压缩"。

而窗口函数:

可以一边保留原数据,一边做统计。


二、窗口函数基本语法

sql 复制代码
函数名() OVER()

比如:

sql 复制代码
SELECT
    name,
    score,
    ROW_NUMBER() OVER()
FROM student;

三、OVER() 到底是什么

这个是窗口函数的核心。

你可以把它理解成:

"规定统计范围"

比如:

sql 复制代码
OVER()

表示:

sql 复制代码
对整个结果集进行处理

四、第一个窗口函数:ROW_NUMBER()

作用:

给每一行编号。


示例

sql 复制代码
SELECT
    name,
    score,
    ROW_NUMBER() OVER() AS rn
FROM student;

结果:

name score rn
张三 90 1
李四 85 2
王五 95 3

五、ORDER BY 很重要

窗口函数通常会配合:

sql 复制代码
ORDER BY

一起使用。


按成绩排名

sql 复制代码
SELECT
    name,
    score,
    ROW_NUMBER() OVER(
        ORDER BY score DESC
    ) AS rn
FROM student;

结果:

name score rn
王五 95 1
张三 90 2
李四 85 3

六、RANK() 和 ROW_NUMBER() 的区别

这是面试高频。

很多人容易搞混。


数据

name score
张三 90
李四 90
王五 85

1.ROW_NUMBER()

sql 复制代码
SELECT
    name,
    score,
    ROW_NUMBER() OVER(
        ORDER BY score DESC
    ) AS rn
FROM student;

结果:

name score rn
张三 90 1
李四 90 2
王五 85 3

特点:

sql 复制代码
即使分数相同,
排名也不会重复

2.RANK()

sql 复制代码
SELECT
    name,
    score,
    RANK() OVER(
        ORDER BY score DESC
    ) AS rk
FROM student;

结果:

name score rk
张三 90 1
李四 90 1
王五 85 3

特点:

sql 复制代码
相同分数排名一样,
但会跳名次

3.DENSE_RANK()

sql 复制代码
SELECT
    name,
    score,
    DENSE_RANK() OVER(
        ORDER BY score DESC
    ) AS dr
FROM student;

结果:

name score dr
张三 90 1
李四 90 1
王五 85 2

特点:

sql 复制代码
相同分数排名一样,
但不会跳名次

七、PARTITION BY(超级重要)

这个是窗口函数真正强大的地方。

你可以理解成:

"分组后,再在组内操作"

类似:

sql 复制代码
GROUP BY

但:

sql 复制代码
不会压缩数据

示例数据

name class score
张三 1班 90
李四 1班 85
王五 2班 95
赵六 2班 88

查询每个班的排名

sql 复制代码
SELECT
    name,
    class,
    score,
    ROW_NUMBER() OVER(
        PARTITION BY class
        ORDER BY score DESC
    ) AS rn
FROM student;

结果:

name class score rn
张三 1班 90 1
李四 1班 85 2
王五 2班 95 1
赵六 2班 88 2

八、SUM() 也能做窗口函数

这个很多人不知道。


查询累计工资

month salary
1 1000
2 1500
3 2000

累计求和

sql 复制代码
SELECT
    month,
    salary,
    SUM(salary) OVER(
        ORDER BY month
    ) AS total
FROM salary;

结果:

month salary total
1 1000 1000
2 1500 2500
3 2000 4500

九、窗口函数和 GROUP BY 的区别

这是核心。


GROUP BY

特点:

sql 复制代码
会压缩数据

比如:

sql 复制代码
SELECT class,
AVG(score)
FROM student
GROUP BY class;

最后:

sql 复制代码
一组只剩一行

窗口函数

特点:

sql 复制代码
保留原数据

比如:

sql 复制代码
SELECT
    name,
    score,
    AVG(score) OVER()
FROM student;

每个人的数据都还在。


十、实际开发中的经典场景


1.排行榜

sql 复制代码
RANK()
ROW_NUMBER()

2.分页

sql 复制代码
ROW_NUMBER()

3.TopN 查询

比如:

sql 复制代码
每个班前3名

4.累计统计

sql 复制代码
SUM() OVER()

5.环比分析

sql 复制代码
LAG()
LEAD()

十一、LAG() 和 LEAD()

这个在数据分析里特别常见。


LAG()

取上一行数据。

sql 复制代码
SELECT
    month,
    salary,
    LAG(salary) OVER(
        ORDER BY month
    ) AS prev_salary
FROM salary;

LEAD()

取下一行数据。

sql 复制代码
SELECT
    month,
    salary,
    LEAD(salary) OVER(
        ORDER BY month
    ) AS next_salary
FROM salary;

十二、新手最容易懵的点


1.OVER() 必须写

窗口函数一定要配:

sql 复制代码
OVER()

2.PARTITION BY 不是 GROUP BY

它只是:

sql 复制代码
组内操作

不会压缩数据。


3.ORDER BY 非常重要

很多窗口函数:

sql 复制代码
排名
累计
上一行
下一行

都依赖排序。


十三、最结

窗口函数本质:

在不减少原数据的情况下做统计。


最核心的几个函数

函数 作用
ROW_NUMBER() 行号
RANK() 排名(跳名次)
DENSE_RANK() 排名(不跳名次)
SUM() OVER() 累计求和
LAG() 上一行
LEAD() 下一行

最核心的语法

sql 复制代码
函数名() OVER(
    PARTITION BY 分组
    ORDER BY 排序
)

sql 复制代码
窗口函数 = 保留原数据 + 做统计
相关推荐
贺国亚9 小时前
Prompt-Injection攻防与OWASP-LLM
后端
卷无止境9 小时前
《Deep Analysis with Polars》进阶分析技巧——深入解读
后端·python
2401_873479409 小时前
如何识别代理IP和伪装流量?用IP情报工具三步穿透住宅代理伪装
网络·数据库·网络协议·tcp/ip·ip
诚信定制8399 小时前
如何启动 Redis 服务:详细步骤指南
数据库·redis·缓存
AllData公司负责人9 小时前
数据同步平台|AIIData数据中台实现MySQL、Hive、Kafka 一键接入Doris
大数据·数据库·hive·mysql·kafka·实时同步
数据库小学妹9 小时前
MySQL安全加固全流程:网络隔离、TDE加密、数据脱敏、等保合规7步实战
mysql·安全·数据脱敏·审计日志·安全加固·等保合规
Edward111111119 小时前
一AI名词
java·开发语言·数据库·学习
hey you~9 小时前
400电话选型技术测评:一个开发视角的线路质量评估方案
运维·网络·数据库·400电话·企业通信
Database_Cool_10 小时前
实时计数器/排行榜首选:阿里云 Tair 高并发数据结构实践
数据结构·数据库·阿里云·云计算
言乐610 小时前
Python视频相对亮度检测
数据库·python·计算机视觉·小程序·音视频