FILTER子句仅PostgreSQL 9.4+及少数现代数据库支持,MySQL等主流数据库不支持;它必须紧跟聚合函数、括号内仅限布尔表达式,语义等价于CASE但更简洁。
FILTER 子句只在 PostgreSQL 和少数现代数据库中可用
MySQL、SQL Server、SQLite(除非 3.30+ 且编译时启用)都不支持 FILTER。你看到的语法错误,大概率是因为数据库不认这个关键字。PostgreSQL 9.4+ 才引入 FILTER,它是标准 SQL:2003 的一部分,但落地缓慢。别在 MySQL 里试 COUNT(*) FILTER (WHERE status = 'active')——直接报错 syntax error at or near "FILTER"。
PostgreSQL 中 FILTER 必须紧跟聚合函数,不能独立存在
FILTER 不是 WHERE 的替代品,它只修饰单个聚合函数调用,作用域仅限于该函数内部。常见误写是把它放在 GROUP BY 后或试图复用条件:
SELECT COUNT(*) FILTER (WHERE paid), AVG(amount) FILTER (WHERE paid AND amount > 0), SUM(amount) FILTER (WHERE status = 'shipped') -- ✅ 每个聚合可独立加 FILTER FROM orders;
这些条件互不影响,也不改变分组逻辑。注意:FILTER 后面必须是 (WHERE ...) 形式,括号不能省,里面只能是布尔表达式,不支持 ORDER BY 或子查询。
FILTER 比 CASE 更简洁,但性能未必更好
语义上,COUNT(*) FILTER (WHERE x) 等价于 COUNT(CASE WHEN x THEN 1 END),但前者少打字、逻辑更直白。不过执行计划通常一致——PostgreSQL 会把两者都转成相同路径。实际差异在于可读性和维护性: