42 CASE
CASE is SQL’s conditional expression — the closest thing to an if/else. It has two forms. The searched CASE (CASE WHEN cond THEN ... END) evaluates arbitrary boolean conditions. The simple CASE (CASE expr WHEN value THEN ... END) compares an expression to specific values. CASE can be used anywhere an expression is allowed — in SELECT, WHERE, ORDER BY, GROUP BY, and in expressions inside aggregates.
What you’ll learn
- Searched
CASEfor general conditions - Simple
CASEfor value equality ELSEand what happens without it- Using
CASEto bucket rows for grouping - The role of
CASEin conditional aggregation (and whenFILTERreplaces it)
Example
The searched form is the workhorse. PostgreSQL evaluates conditions top-to-bottom and returns the result of the first true one. If no condition matches and there is no ELSE, the result is NULL — sometimes useful, sometimes a bug.
The simple form is shorthand for equality: CASE name WHEN 'a' THEN ... END is the same as CASE WHEN name = 'a' THEN ... END. It is concise when you have many discrete values to map.
Conditional aggregation — counting or summing only matching rows — used to require sum(CASE WHEN cond THEN val ELSE 0 END). sum(val) FILTER (WHERE cond) expresses the condition directly. It can return NULL where sum(CASE WHEN cond THEN val ELSE 0 END) returns 0 (when input rows exist but none match). Use COALESCE if zero is the intended empty-result value.
Run the example
To run:
Common pitfalls
- All
THEN/ELSEbranches must agree on a common type —CASE WHEN ... THEN 1 ELSE 'x' ENDis an error. Cast explicitly when mixing types:CASE WHEN ... THEN 1::text ELSE 'x' END. - Forgetting
ENDis the most common syntax error. - Without
ELSE, the result isNULLwhen no branch matches. If that is surprising, add an explicitELSE .... CASEinWHEREworks but is usually unnecessary — most conditions are clearer as plain boolean expressions.
CASE and COALESCE overlap but are not the same. COALESCE(a, b, c) is shorter for “first non-null”; CASE is the right choice when conditions are not just “is null.”
Use CASE to map id to a label like ‘small’ / ‘medium’ / ’large’ and count per label. Use CASE in ORDER BY to sort priorities in a custom order: ORDER BY CASE priority WHEN 'high' THEN 1 WHEN 'mid' THEN 2 ELSE 3 END. Then rewrite a sum(CASE WHEN ...) as sum(...) FILTER (WHERE ...).
Downloads
SQL file: case.sql · All lesson files · Setup guide