📌 今日关键词: 窗口函数模板、SQL速查、新手友好、排名计算、累计求和
大家好呀!我是数据库小学妹 👋
上午我们硬核攻克了窗口函数(Window Function),是不是感觉脑子被 OVER、PARTITION BY 这些单词塞得满满当当?😵
💫别担心!记不住复杂的语法很正常,其实90%的窗口函数场景,只需要记住3个“填空题”模板就够了!✍️
今天这篇就是专门为你准备的“防忘速查小抄”。遇到问题时,直接把字段名填进去,一行代码都不用改,直接复制就能跑!🚀
📝 模板一:万能排名公式(Top N 问题)
适用场景: 每个班级/部门取前3名;找出销量最高的产品。
核心逻辑: ROW_NUMBER() / RANK() + PARTITION BY 分组 + ORDER BY 排序
-- 【万能模板】
SELECT *
FROM (
SELECT
列1, 列2,
ROW_NUMBER() OVER (PARTITION BY 分组字段 ORDER BY 排序字段 DESC) AS 排名别名
FROM 表名
) AS 临时表别名
WHERE 排名别名 <= N; -- N代表你想取的前几名
💡 填空示范(取每个班级前2名):
SELECT *
FROM (
SELECT
class, student_name, score,
ROW_NUMBER() OVER (PARTITION BY class ORDER BY score DESC) AS rn
FROM class_scores
) AS ranked
WHERE rn <= 2;
📝 模板二:累计求和公式(移动平均/年累计)
适用场景: 计算每天的“累计销售额”;计算每月相比上月的增长率。
核心逻辑: SUM() / AVG() + ORDER BY + ROWS 窗口范围
-- 【万能模板】
SELECT
时间字段,
数值字段,
SUM(数值字段) OVER (
ORDER BY 时间字段
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS 累计别名
FROM 表名;
💡 填空示范(计算月累计销售额):
SELECT
month,
amount,
SUM(amount) OVER (
ORDER BY month
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS cumulative_amount
FROM sales;
📝 模板三:跨行对比公式(同比/环比/上期对比)
适用场景: 本月比上月多了多少?(核心是 LAG 和 LEAD)
核心逻辑: LAG() 向上取数,LEAD() 向下取数。
-- 【万能模板】
SELECT
时间字段,
当前数值,
LAG(当前数值, 1) OVER (ORDER BY 时间字段) AS 上期数值, -- 1代表取上一行
当前数值 - LAG(当前数值, 1) OVER (ORDER BY 时间字段) AS 差值
FROM 表名;
💡 填空示范(对比上个月的销量):
SELECT
month,
sales,
LAG(sales, 1) OVER (ORDER BY month) AS last_month_sales,
sales - LAG(sales, 1) OVER (ORDER BY month) AS diff
FROM monthly_sales;
⚠️ 避坑特别提醒(新手必看!)
虽然模板好用,但小学妹还是要提醒你两个“防翻车”的小细节:
- MySQL版本号:
- 坑点: 如果你的MySQL版本是 5.7 或更早,上面的代码会直接报错!
- 解法: 窗口函数是 MySQL 8.0+ 才有的新特性。如果你还在用旧版本,请先升级,或者用自连接(Self-Join)这种笨办法来实现(虽然很难写,但能跑)。
- CTE的使用:
- 坑点: 为什么不能直接在
WHERE里写WHERE rn <= 2? - 解法: 因为SQL的执行顺序,
WHERE在SELECT之前。所以必须把带窗口函数的查询包在一个子查询(或者用WITH语句)里,先算出排名,再在外面一层WHERE过滤。
- 坑点: 为什么不能直接在
👋 我是数据库小学妹一个用设计师思维学数据库的转行人。我们一起,把复杂的技术变得简单有趣!💕
本文示例基于 MySQL 8.0。版本低于8.0不支持窗口函数,建议升级或使用其他方法替代。