好,这个题目非常偏“进阶 SQL + 面试/实战”,我就直接给你一份能抄走用、也能讲给面试官听的《SQL 窗口函数实践笔记》。
不灌水,**以“为什么 → 怎么写 → 什么时候用”**为主。
SQL 窗口函数实践笔记(Window Functions)
一、为什么要用窗口函数?
一句话概括:
窗口函数 = 在“不减少行数”的前提下做统计分析
对比一下 👇
传统 GROUP BY 的问题
SELECT dept, AVG(salary)
FROM emp
GROUP BY dept;
- 会 丢行
- 不能看到“每个人 + 部门平均值”
窗口函数能做到什么?
SELECT
name,
dept,
salary,
AVG(salary) OVER (PARTITION BY dept) AS dept_avg
FROM emp;
✅ 行不丢
✅ 统计结果“贴”在每一行上
二、窗口函数的基本语法(核心)
函数名(...) OVER (
PARTITION BY ...
ORDER BY ...
ROWS / RANGE ...
)
| 子句 | 作用 |
|---|---|
| PARTITION BY | 分组(逻辑分组,不合并行) |
| ORDER BY | 窗口内排序 |
| ROWS / RANGE | 窗口范围 |
三、常用窗口函数分类
1️⃣ 聚合类窗口函数
示例:部门平均工资
AVG(salary) OVER (PARTITION BY dept)
常见函数:
SUM()AVG()COUNT()MAX()MIN()
📌 区别于 GROUP BY:不合并行
2️⃣ 排名类窗口函数(高频)
ROW_NUMBER(不并列)
ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC)
RANK(并列跳号)
RANK() OVER (ORDER BY score DESC)
DENSE_RANK(并列不跳号)
DENSE_RANK() OVER (ORDER BY score DESC)
| 分数 | RANK | DENSE_RANK |
|---|---|---|
| 100 | 1 | 1 |
| 90 | 2 | 2 |
| 90 | 2 | 2 |
| 80 | 4 | 3 |
3️⃣ 偏移函数(分析神器)
LAG / LEAD
LAG(salary, 1) OVER (ORDER BY month)
👉 取“上一行 / 下一行”的值
常见场景
- 环比
- 同比
- 增长率
4️⃣ 分布类函数(了解)
NTILE(n):分桶PERCENT_RANK()CUME_DIST()
四、窗口范围(ROWS vs RANGE)
1️⃣ ROWS(基于行)
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
- 精确
- 推荐使用
2️⃣ RANGE(基于值)
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
- 可能包含多行
- 小心重复值
📌 实战建议:优先 ROWS
五、实战案例(直接可用)
1️⃣ 每个部门工资排名 Top 3
SELECT *
FROM (
SELECT
name,
dept,
salary,
ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC) AS rn
FROM emp
) t
WHERE rn <= 3;
🔥 面试必会
2️⃣ 计算工资环比增长
SELECT
month,
salary,
salary - LAG(salary) OVER (ORDER BY month) AS diff
FROM emp_salary;
3️⃣ 累计求和
SUM(sales) OVER (
ORDER BY day
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS total_sales
4️⃣ 去重保留最新一条
SELECT *
FROM (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY update_time DESC) rn
FROM user_log
) t
WHERE rn = 1;
六、窗口函数执行顺序(面试点)
SQL 执行顺序(简化):
FROM
→ WHERE
→ GROUP BY
→ HAVING
→ SELECT
→ WINDOW FUNCTION
→ ORDER BY
📌 窗口函数 不能写在 WHERE 中
七、性能 & 实战注意点
- 窗口函数 ≠ 免费
PARTITION BY可能导致排序- 大表务必:
- 控制窗口范围
- 合理加索引(order by 字段)
八、MySQL / PostgreSQL / Oracle 支持情况
- MySQL:8.0+
- PostgreSQL:强(最早支持)
- Oracle:成熟
九、面试一句话总结
窗口函数用于在不合并结果行的情况下进行排序、排名和统计分析,是分析型 SQL 的核心能力,常用于 TopN、环比、累计值等场景。
十、速记口诀(很有用)
GROUP BY 会合并行,窗口函数不合并;
排名用 ROW_NUMBER,分析用 LAG/LEAD。
如果你愿意,我可以下一步直接帮你:
- 🔥 SQL 窗口函数面试 10 连问
- 🔥 MySQL 窗口函数执行计划分析
- 🔥 窗口函数 vs 子查询 vs Join 对比
- 🔥 实际业务场景建模(报表 / BI)
你是 数据分析 / 后端开发 / 面试准备 哪个方向?