CASE Expressions: Conditional Logic in SQL
Use CASE WHEN to bucket employees into salary bands, and inside COUNT() to conditionally tally rows.
Overview
A CASE expression is SQL's inline if/else: it evaluates a series of
conditions in order and returns the value tied to the first one that's true,
falling back to ELSE if none match. It behaves like a normal column in
SELECT, so you can name it with AS, sort by it, filter on it, or nest it
inside an aggregate function.
Common real-world uses: turning a numeric value into a labeled category (salary band, age group, price tier), or building a conditional count/sum without writing several separate queries.
The Query
Loading database engine...
Step-by-Step Breakdown
CASE— starts the expression.WHEN salary > 100000 THEN 'High'— checked first. If true, the expression evaluates to'High'and no further branches are checked for that row.WHEN salary > 75000 THEN 'Mid'— only reached if the first condition was false. Order matters: this branch implicitly means "salary is 75,000 or less but this line wasn't reached unless the firstWHENalready failed," so it correctly covers the 75,000–100,000 range.ELSE 'Entry'— the fallback for every row that didn't match anyWHENabove.END AS salary_band— closes the expression and names the resulting column.
Because WHEN clauses are evaluated top to bottom and the first match wins,
the order of your conditions is part of the logic, not just style.
Variations
Use CASE inside an aggregate to conditionally count rows:
Loading database engine...
CASE WHEN salary > 100000 THEN 1 END returns 1 for qualifying rows and
NULL (via the implicit, unwritten ELSE) for every other row. COUNT()
ignores NULLs, so COUNT(CASE WHEN ... THEN 1 END) effectively counts only
the rows matching the condition — a common way to compute several
conditional totals in one pass over the data instead of running separate
filtered queries.
An omitted ELSE defaults to NULL
Leaving off ELSE doesn't cause an error — the expression simply
evaluates to NULL for any row that matches no WHEN. That's exactly
what makes the COUNT(CASE WHEN ... THEN 1 END) pattern work: rows that
don't match the condition contribute NULL, which COUNT skips.
Common Mistakes
- Ordering
WHENclauses incorrectly. PuttingWHEN salary > 75000beforeWHEN salary > 100000would mean every high earner also satisfies the first, broader condition — they'd all end up labeled'Mid'and the'High'branch would never be reached. - Forgetting
CASEreturns a single value per row, not a filter. ACASEexpression labels or transforms a row; it doesn't remove rows from the result the wayWHEREdoes. - Mixing incompatible return types across branches. Every
THEN(andELSE) value should resolve to a comparable type — mixing text and numbers across branches can force unexpected type coercion. - Using
COUNT(CASE WHEN x THEN 1 ELSE 0 END)instead of omittingELSE. Both produce the same count in most databases, butCOUNT(CASE WHEN x THEN 1 END)(noELSE) is the clearer idiom, since it relies onCOUNTignoringNULLrather than summing zeros.