Aggregates With FILTER (Conditional Aggregation)
Count completed vs cancelled orders in one pass using FILTER clauses.
Overview
DuckDB (and Postgres) support a FILTER (WHERE …) clause on aggregates, letting
you compute conditional aggregates in a single GROUP BY query, no CASE
required. Here we count completed and cancelled orders per product category side
by side.
The Query
Loading playground environment...
Step-by-Step Breakdown
COUNT(*) FILTER (WHERE o.status = 'completed'): counts only completed orders in each category.COUNT(*) FILTER (WHERE o.status = 'cancelled'): counts only cancelled ones.- Both share the same
GROUP BY p.category, so they align per category.
FILTER vs CASE
COUNT(*) FILTER (WHERE …) is equivalent to COUNT(CASE WHEN … THEN 1 END)
but reads more cleanly and is often faster.
Variations
Average salary of active vs all employees per department:
Loading playground environment...
Common Mistakes
- Using FILTER where unsupported. MySQL lacks
FILTER; fall back toCASE. Know your engine. - Forgetting the aggregate.
FILTERmodifies an aggregate; you can't writecol FILTER (WHERE …)on a bare column. - Doubling counts.
COUNT(*) FILTERstill respects theGROUP BY; don't also add aWHERE status = …that drops the other rows you wanted to count.
Cite this resource
SQLSimplified. "Aggregates With FILTER (Conditional Aggregation) Example". Available at: https://sqlsimplified.online/examples/aggregate-with-filter