Conditional logic & CASE
Concept  ·  SQL & Querying

agg(...) FILTER (WHERE ...) is the cleaner dialect form of conditional aggregation.

FILTER says what the CASE spelling implies: 'this aggregate, over this subset.' The equivalence is exact for SUM/MIN/MAX; for COUNT it's cleaner than CASE (no missing-ELSE reasoning). The portability tax is the dialect half: Postgres/DuckDB/SQLite yes; BigQuery/SQL Server/MySQL no (CASE is the travel kit). Pick one spelling per codebase; mixed reports make reviewers re-verify equivalence line by line.

See it break
feed
otterkindg
o1fish10
o1crab5
The trap
SELECT
  otter,
  SUM(
    CASE
      WHEN kind = 'fish' THEN g
    END
  ) AS fish
FROM
  feed
GROUP BY
  otter;
The fix
SELECT
  otter,
  SUM(g) FILTER(
    WHERE
      kind = 'fish'
  ) AS fish
FROM
  feed
GROUP BY
  otter;
INPUTYour queryThe fix
o11010

Both spellings give the same fish grams — FILTER (WHERE …) wears the condition on the outside of the aggregate, identical semantics to the CASE form but clearer, and narrower in portability (Postgres/DuckDB yes; BigQuery/MySQL no).

The rule

FILTER where it lives, CASE as the portable expansion; one spelling per codebase.

FILTER (WHERE …) in Postgres/DuckDB/SQLite; expand to CASE on BigQuery/SQL Server/MySQL.

Shows up elsewhere
Conditional aggregationQUALIFY idiom
Try one →Prove it in practice →