Skip to content
MySQL 建模与查询优化 · 第 5 篇 / 共 6 篇
领域数据与中间件
专题MySQL 专题
当前序列MySQL 建模与查询优化
阅读位置第 5 篇 / 共 6 篇当前专题第 1 个序列 / 共 7 个序列

SQL 开窗函数入门:ROW_NUMBER、RANK、LAG 这些函数到底怎么用

开窗函数是 SQL 里非常实用的一类能力,尤其适合做:

  • 排名
  • 分组内排序
  • 上一行 / 下一行对比
  • 同组内累计分析

如果只是背函数名,通常很快就会忘。真正更好记的方式是先理解它到底解决了什么问题。

一、开窗函数解决什么问题

你可以把它理解成:

在不把结果集“聚合成一行”的前提下,对某个分组窗口里的数据做分析计算。

这点和普通聚合函数最大的区别在于:

  • 普通聚合经常会把多行压成一行
  • 开窗函数通常仍然保留原始行,只是在每一行上附加分析结果

二、最常见的几个函数

1. ROW_NUMBER()

作用:给每一行生成一个唯一递增序号。

适合场景:

  • 组内排序后取第一条
  • 做分页辅助排序

2. RANK()

作用:计算排名,遇到并列时名次会跳跃。

例如分数:

  • 100 分,第 1 名
  • 100 分,第 1 名
  • 90 分,第 3 名

3. DENSE_RANK()

作用:计算排名,遇到并列时名次不会跳跃。

例如分数:

  • 100 分,第 1 名
  • 100 分,第 1 名
  • 90 分,第 2 名

4. LAG()

作用:取当前行之前某一行的值。

适合场景:

  • 和上一条记录比较
  • 看环比、趋势变化

5. LEAD()

作用:取当前行之后某一行的值。

适合场景和 LAG() 类似,只是方向相反。

6. FIRST_VALUE() / LAST_VALUE()

作用:取窗口内的第一个值或最后一个值。

适合场景:

  • 看某个分组里的首条状态
  • 看一段时间里的起点和终点值

三、一个最简单的理解框架

学习开窗函数时,可以先把语句结构记成这样:

sql
函数() over (
  partition by 分组字段
  order by 排序字段
)

其中:

  • partition by:决定按什么分组
  • order by:决定窗口内的顺序

如果没有 partition by,就表示整个结果集当成一个窗口。

四、典型使用场景

场景 1:每个部门工资最高的员工

可以先按部门分组,再按工资倒序,用 ROW_NUMBER() 给每组排序,然后取每组第 1 条。

场景 2:看销量排名

可以用 RANK()DENSE_RANK()

场景 3:和上一天数据做对比

可以用 LAG() 取前一天的值,再做差值计算。

五、一个容易混淆的点

很多人刚开始会把“分组”理解成 GROUP BY

但两者并不一样:

  • GROUP BY 通常会改变结果集行数
  • 开窗函数分析后,原始明细行通常还在

所以它特别适合“既想保留明细,又想做统计分析”的场景。

一句话总结

开窗函数最有价值的地方在于:

不破坏原始明细行的前提下,对分组内的数据做排序、排名、对比和分析。

如果你经常写报表、排行、趋势分析 SQL,这类函数几乎迟早都会用到。

延伸阅读相关文章优先当前专题,再补跨专题关联。
同一序列 · 顺着当前主线继续读MySQL 慢 SQL 优化案例适合先把字段设计、索引、Explain、分页和慢 SQL 这条主线走顺。MySQL 专题 · MySQL 建模与查询优化同一序列 · 回看前文会更完整MySQL 分页优化适合先把字段设计、索引、Explain、分页和慢 SQL 这条主线走顺。MySQL 专题 · MySQL 建模与查询优化同专题其他序列 · MySQL 变更与运维治理大表在线 DDL 怎么做更稳适合把计数、日志、在线变更和归档清理放在一起看。MySQL 专题 · MySQL 变更与运维治理同专题其他序列 · MySQL 变更治理与数据生命周期大事务为什么会拖垮数据库适合把大事务、DDL、回填、慢 SQL 治理和归档分层放进一条持续治理主线上看。MySQL 专题 · MySQL 变更治理与数据生命周期跨专题关联 · 同场景:基础学习设计模式总览适合把设计模式、对象创建和结构抽象能力放在一组里系统理解。架构与设计专题 · 设计模式与结构抽象跨专题关联 · 同场景:基础学习ClickHouse 入门适合把 ClickHouse 入门、表设计、慢查询和看板性能问题放在一起连续看。ClickHouse 专题 · ClickHouse 表设计与查询优化
继续阅读MySQL 建模与查询优化当前序列第 5 篇 / 共 6 篇当前专题第 1 个序列 / 共 7 个序列
往前看
上一篇MySQL 分页优化回到当前序列上一章上一序列设计模式与结构抽象从第 1 篇开始:设计模式总览
往后看
下一篇MySQL 慢 SQL 优化案例继续当前序列下一章下一序列MySQL 事务、锁与高可用从第 1 篇开始:MySQL 事务与锁

把零散经验整理成可查、可复用、可持续更新的企业级知识门户