SQL窗口函数

语法与窗口框架

-- 基本语法 function_name() OVER ( [PARTITION BY col1, col2] -- 可选:分组 [ORDER BY col3 DESC] -- 可选:组内排序 [ROWS|RANGE BETWEEN ... AND ...] -- 可选:定义框架 ) -- 框架边界: -- UNBOUNDED PRECEDING — 分区起始 -- N PRECEDING — 当前行之前 N 行/范围 -- CURRENT ROW — 当前行 -- N FOLLOWING — 当前行之后 N 行/范围 -- UNBOUNDED FOLLOWING — 分区结束 -- 命名窗口(多个函数复用) SELECT dept, salary, SUM(salary) OVER w AS dept_sum, AVG(salary) OVER w AS dept_avg FROM employees WINDOW w AS (PARTITION BY dept);

函数参考

函数说明备注
ROW_NUMBER()唯一连续整数(1,2,3...)无并列,始终唯一
RANK()有间隔的排名(1,1,3...)并列后跳过编号
DENSE_RANK()无间隔的排名(1,1,2...)不跳过编号
NTILE(n)分成 n 桶(1到n)适合分位数计算
LAG(col, n, 默认值)前 n 行的值n 默认为 1
LEAD(col, n, 默认值)后 n 行的值n 默认为 1
FIRST_VALUE(col)框架内第一个值需要明确框架
LAST_VALUE(col)框架内最后一个值需 ... AND UNBOUNDED FOLLOWING
SUM/AVG/COUNT/MIN/MAX滚动/移动聚合框架控制包含范围

实用示例

-- 分组 Top N(每个部门薪资前3) WITH ranked AS ( SELECT name, dept, salary, ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC) AS rn FROM employees ) SELECT name, dept, salary FROM ranked WHERE rn <= 3; -- 同比增长 SELECT year, revenue, LAG(revenue) OVER (ORDER BY year) AS prev_year, ROUND(100.0 * (revenue - LAG(revenue) OVER (ORDER BY year)) / NULLIF(LAG(revenue) OVER (ORDER BY year), 0), 1) AS yoy_pct FROM annual_revenue; -- 7日移动平均 SELECT date, daily_sales, ROUND(AVG(daily_sales) OVER ( ORDER BY date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW ), 2) AS moving_avg_7d FROM daily_sales; -- 用户累计消费(分区重置) SELECT user_id, order_date, amount, SUM(amount) OVER ( PARTITION BY user_id ORDER BY order_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS lifetime_value FROM orders;