目录
1. 窗口函数:像班级排名一样分析数据
1.1 什么是窗口函数?
想象你有一张全班成绩表,要回答这些问题:
- 王同学在班里排第几?(排名)
- 他比前一名高多少分?(差值)
- 他的成绩占全班总分多少比例?(占比)
如果用普通SQL,需要多次查询+临时表。而窗口函数就像给你的数据开了一个"滑动窗口",直接在一行里算出这些复杂结果!
-- 基础语法(重点记这个!)
SELECT
<列>,
RANK() OVER (PARTITION BY 班级 ORDER BY 成绩 DESC) AS 排名
FROM 成绩表;
1.2 三大排名函数对比(附生活案例)
函数 | 特点 | 生活案例 |
---|---|---|
RANK() | 并列跳号(1,1,3) | 奥运奖牌:金牌两人,下个是铜牌 |
DENSE_RANK() | 并列不跳号(1,1,2) | 考试排名:两人并列第一,下个第二 |
ROW_NUMBER() | 强制连续序号(1,2,3) | 电影院座位号:必须连续 |
代码示例:
-- 按商品价格排名
SELECT
product_name,
price,
RANK() OVER (ORDER BY price DESC) AS '跳位排名',
DENSE_RANK() OVER (ORDER BY price DESC) AS '不跳位排名',
ROW_NUMBER() OVER (ORDER BY price DESC) AS '强制连续排名'
FROM products;
1.3 累计统计:你的工资今年涨了多少?
场景:计算每个月的工资累计值(类似支付宝年度账单)
SELECT
month,
salary,
SUM(salary) OVER (ORDER BY month) AS '累计工资'
FROM salary_table;
输出效果:
month | salary | 累计工资 |
---|---|---|
1 | 10000 | 10000 |
2 | 11000 | 21000 |
3 | 12000 | 33000 |
1.4 移动平均:预测股票走势的秘密武器
场景:计算近3天的平均股价(平滑波动)
SELECT
date,
stock_price,
AVG(stock_price) OVER (
ORDER BY date
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
) AS '3日移动平均'
FROM stock_data;
效果解释:
- 2023-01-03的均值 = (01价格 + 02价格 + 03价格)/3
- 2023-01-04的均值 = (02价格 + 03价格 + 04价格)/3
2. GROUPING运算符:自动生成Excel式合计行
2.1 ROLLUP:自动加小计和总计
场景:统计每个部门的薪资,并自动生成部门小计和公司总计
SELECT
COALESCE(department, '公司总计') AS 部门,
SUM(salary) AS 总工资
FROM employees
GROUP BY ROLLUP(department);
输出结果:
研发部 500000
销售部 300000
公司总计 800000
2.2 CUBE:所有维度组合统计
场景:同时按部门和职级统计工资,生成所有可能的组合
SELECT
department,
job_level,
SUM(salary)
FROM employees
GROUP BY CUBE(department, job_level);
生成组合包括:
- 各部门各职级
- 各部门总计
- 各职级总计
- 公司总计
2.3 GROUPING SETS:只生成我需要的统计
场景:只想要部门总计和职级总计,不要其他组合
SELECT
department,
job_level,
SUM(salary)
FROM employees
GROUP BY GROUPING SETS ((department), (job_level));
3. 实战技巧+避坑指南
✅ 必看技巧
- 性能优化:窗口函数中
ORDER BY
的列尽量有索引 - 框架范围:
ROWS BETWEEN ...
:按物理行数RANGE BETWEEN ...
:按逻辑值范围
- 处理NULL值:用
COALESCE()
替换分组产生的NULL
⚠️ 常见错误
-- 错误!窗口函数不能直接用在WHERE中
SELECT name, RANK() OVER(...)
FROM table
WHERE RANK() <= 3; -- 报错!
-- 正确做法:用子查询
SELECT * FROM (
SELECT name, RANK() OVER(...) AS rk
FROM table
) WHERE rk <= 3;
4. 互动问答+学习资源
🤔 小测验(答案见评论区)
测试数据表
-- 学生成绩表(students)
CREATE TABLE students (
student_id INT PRIMARY KEY,
name VARCHAR(50),
class VARCHAR(20), -- 班级
score INT -- 考试成绩
);
INSERT INTO students VALUES
(1, '张三', 'A班', 85),
(2, '李四', 'A班', 90),
(3, '王五', 'B班', 78),
(4, '赵六', 'B班', 78),
(5, '陈七', 'B班', 92);
题目1:计算每个学生的成绩比前一名高多少分
要求:按班级分组,按成绩降序排名,并显示与前一名成绩的差值。
提示:使用 LAG()
窗口函数
题目2:ROLLUP和CUBE的区别是什么?
要求:用一句话说明两者差异,并举例说明。
📚 推荐学习资源
- 图书:《SQL进阶教程》MICK著
- 在线练习:SQLZoo窗口函数练习
- 视频:B站窗口函数实战
🎉 恭喜!你已经掌握了SQL高级处理的核心技能!
🎯下期预告:《通过应用程序连接数据库》
💬互动话题:你在学习SQL时遇到过哪些坑?欢迎评论区留言讨论!
🏷️温馨提示:我是[随缘而动,随遇而安], 一个喜欢用生活案例讲技术的开发者。如果觉得有帮助,点赞关注不迷路🌟