场景 1:分组内排名(Top N 问题) 最常见
需求:查找每个部门薪水前三名的员工信息。
为什么用它:如果不用窗口函数,你不得不在 Java 里查出所有数据再用 Stream 分组排序,或者在 SQL 里写极其复杂的自连接。
核心函数:ROW_NUMBER()、RANK()、DENSE_RANK()
SQL
-- 给每个部门的员工按薪水降序打上排名序号
SELECT
emp_no,
dept_no,
salary,
ROW_NUMBER() OVER(PARTITION BY dept_no ORDER BY salary DESC) as rk
FROM salaries;
-- 外层再套一个 SELECT 查 rk <= 3 即可拿到 Top 3
场景 2:跨行比较(和上一行/下一行对比)
需求:计算某个员工这个月的薪水比上个月涨了多少(环比增长)。
为什么用它:关系型数据库天然是一行一行独立的,正常情况下这一行不知道上一行的数据。窗口函数打破了这个限制。
核心函数:LAG()(获取上一行)、LEAD()(获取下一行)
SQL
SELECT
emp_no,
salary,
LAG(salary, 1) OVER(PARTITION BY emp_no ORDER BY from_date) as prev_salary
FROM salaries;
场景 3:累计求和 / 移动平均
需求:计算某个公司从 1 月到 12 月的累计总收入(1月是1月的钱,2月是1+2月的钱,3月是1+2+3月的钱)。
核心函数:SUM() OVER(ORDER BY ...)
SQL
SELECT
month,
revenue,
SUM(revenue) OVER(ORDER BY month) as cumulative_revenue
FROM sales;
场景 4:既看明细,又看全局聚合
需求:查询所有员工的信息,并在最后加一列显示“该员工薪水与公司平均薪水的差值”。
为什么用它:避免写繁琐的子查询 (SELECT AVG(salary) FROM salaries) 再 JOIN 起来。
SQL
SELECT
emp_no,
salary,
AVG(salary) OVER() as company_avg_salary, -- 整个公司的平均薪水
salary - AVG(salary) OVER() as diff
FROM salaries;
本题答案
SELECT
emp_no,
salary,
SUM(salary) OVER (
ORDER BY
emp_no
) AS running_total
FROM
salaries
WHERE
to_date = '9999-01-01'