窗口函数
窗口函数在保留明细行的同时对相关行计算,形式为 function(...) OVER (...)。普通 GROUP BY 聚合会压缩行数,窗口函数不会。
分区与排序
SELECT customer_id, order_id, amount,
row_number() OVER (PARTITION BY customer_id ORDER BY created_at, order_id) AS seq,
sum(amount) OVER (PARTITION BY customer_id) AS customer_total
FROM orders;
PARTITION BY 划分计算组,ORDER BY 决定组内逻辑顺序;排名应补足唯一排序键,否则并列行之间的 row_number 顺序不确定。rank() 对并列值跳号,dense_rank() 不跳号,percent_rank() 和 cume_dist() 用于相对位置,ntile(n) 近似均分成 n 组。
访问其他行与框架
SELECT order_id, amount,
lag(amount) OVER (ORDER BY created_at, order_id) AS previous_amount,
sum(amount) OVER (
ORDER BY created_at, order_id
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS running_total
FROM orders;
lag、lead 访问前后行,缺少目标行时默认返回 NULL,也可传偏移量和默认值。first_value、last_value、nth_value 受窗口框架影响;有 ORDER BY 时默认框架会包含与当前行排序键相同的同伴行,last_value 常因此不是整个分区的最后值。要统计整组可用 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING,要累计则明确使用上述 ROWS 框架。
顺序与筛选
ROWS 按物理行位置定义框架,RANGE 按排序值及同伴行定义,GROUPS 按同伴组定义。窗口函数只能在 SELECT 列表和 ORDER BY 中使用;要筛选其结果,先在 CTE/子查询中计算,再用外层 WHERE。普通聚合也可以加 OVER 作为窗口聚合,count(*) OVER () 可得到过滤后的总行数,但大结果集要考虑其计算成本。