filter必须紧贴聚合函数右括号后、over前,仅适用于sum、avg、count等聚合类窗口函数,非聚合函数如row_number不支持;其作用域为当前窗口分区内满足条件的行,不改变窗口行集。

FILTER不能和OVER共存,必须放在OVER前面
PostgreSQL 明确禁止 FILTER 与窗口函数混用,写成 sum(sales) OVER (PARTITION BY year) FILTER (WHERE region = 'US') 会直接报错:syntax error at or near "FILTER"。正确顺序只能是 sum(sales) FILTER (WHERE region = 'US') OVER (PARTITION BY year)——FILTER 必须紧贴聚合函数右括号后、OVER 前。
多个FILTER并列时,每个都独立作用于窗口内行
FILTER 的作用域是“当前聚合函数在当前窗口分区内的输入行”,不是全表也不是外部查询。这意味着:
-
COUNT(*) FILTER (WHERE status = 'paid') OVER (PARTITION BY user_id)统计的是每个user_id分区内已支付的订单数 -
AVG(amount) FILTER (WHERE paid AND amount > 0) OVER (PARTITION BY user_id)只对同一用户分区内满足条件的非零金额求均值,空集返回NULL - 不同
FILTER条件互不干扰,但共享同一个窗口定义(即相同的PARTITION BY和ORDER BY)
常见错误:误以为FILTER能过滤窗口范围
FILTER 不改变窗口本身的行集合,它只筛掉聚合计算所用的行。比如:
-
ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC)总是给分区所有行编号 -
ROW_NUMBER() FILTER (WHERE active) OVER (PARTITION BY dept ORDER BY salary DESC)是语法错误——ROW_NUMBER不是聚合函数,不能接FILTER - 想实现“只给活跃员工编号”,得先用
WHERE active或子查询预过滤,再套窗口函数
替代方案:FILTER + 聚合窗口函数是唯一合法组合
只有聚合类窗口函数(SUM、AVG、COUNT、STRING_AGG 等)才支持 FILTER。非聚合函数如 LAG、ROW_NUMBER、RANK 完全不接受 FILTER。若需条件化窗口行为,只能:
- 用
WHERE预过滤数据(影响所有后续窗口) - 在
SELECT中嵌套CASE WHEN处理值(但注意NULL语义) - 用 CTE 先按条件分组或标记,再进窗口计算
最易被忽略的是:空窗口聚合结果为 NULL,而报表常把 NULL 当作“无数据”,实际可能是“该窗口内无一行满足 FILTER 条件”。需要显式用 COALESCE(AVG(...), 0) 或前端做空值判断。










