FILTER clause
The FILTER clause restricts which rows an aggregate function processes, letting you compute multiple conditional aggregates in a single GROUP BY query without CASE expressions.
Overview
The standard SQL FILTER (WHERE condition) clause attaches a row filter directly to an aggregate function call, so a single query can compute several differently-scoped aggregates side by side:
Copy code
SELECT
region,
COUNT(*) AS total_orders,
COUNT(*) FILTER (WHERE status = 'completed') AS completed_orders,
SUM(revenue) FILTER (WHERE channel = 'online') AS online_revenue
FROM orders
GROUP BY region;
FILTER vs CASE WHEN
Before FILTER was widely supported, the same result required wrapping the aggregate's argument in a CASE expression:
Copy code
SELECT
region,
SUM(CASE WHEN channel = 'online' THEN revenue ELSE NULL END) AS online_revenue
FROM orders
GROUP BY region;
FILTER is more readable and makes intent explicit — the condition governs which rows are counted or summed, not what value is substituted. It also composes cleanly with COUNT(*), where a CASE expression would need an awkward THEN 1 ELSE NULL END pattern.
DuckDB specifics
DuckDB fully supports FILTER (WHERE ...) on any aggregate function, including with GROUP BY ALL:
Copy code
SELECT
region,
COUNT(*) FILTER (WHERE status = 'completed') AS completed,
COUNT(*) FILTER (WHERE status = 'cancelled') AS cancelled
FROM orders
GROUP BY ALL;
DuckDB also allows FILTER on window function aggregates (e.g., SUM(x) FILTER (WHERE ...) OVER (...)), which is a more advanced combination not all SQL engines support, letting you compute a filtered running total in one pass.
Related terms
A filter operation selectively includes or excludes records from a dataset based on one or more conditions.
GROUP BY clause →GROUP BY organizes rows into groups for aggregate calculations like SUM, COUNT, and AVG. Learn single and multi-column grouping, HAVING filters, and GROUP BY ALL.
CASE expression →The CASE expression evaluates a list of conditions and returns a corresponding value for the first one that's true, functioning as SQL's if/else logic inside a query.
OVER clause →The OVER clause turns an aggregate or ranking function into a window function by defining the partition, order, and frame it operates on, without collapsing the result set.
aggregate functions →Aggregate functions are SQL operations that perform calculations across multiple rows of data to produce a single summary value.
Bloom filter →A Bloom filter is a space-efficient probabilistic data structure used to test whether a value might be in a set, with no false negatives but a small, tunable rate of false positives.
FAQS
A query-level WHERE clause removes rows before any aggregation happens, affecting every aggregate in the SELECT list. FILTER (WHERE ...) attaches a condition to one specific aggregate function, so different aggregates in the same query can each look at a different subset of rows.
Yes — COUNT(*) FILTER (WHERE condition) counts only the rows matching the condition, which is more direct than the equivalent CASE-expression workaround.
