CASE
PG 7.4+→ common type of all result expressionsGeneral conditional expression. Evaluates conditions in order and returns the result for the first true condition, or the ELSE value if none match.
Signatures
CASE WHEN condition THEN result [WHEN ...] [ELSE default] ENDCASE expression WHEN value THEN result [WHEN ...] [ELSE default] ENDParameters
| Parameter | Type | Description |
|---|---|---|
| condition | boolean | Each WHEN clause is evaluated in order |
| result | any | Value returned when the corresponding condition is true |
| default | any | Value returned if no condition matches; NULL if ELSE is omitted |
Examples
SELECT CASE WHEN score >= 90 THEN 'A' WHEN score >= 80 THEN 'B' WHEN score >= 70 THEN 'C' ELSE 'F' END AS grade FROM results;Letter gradeSELECT CASE status WHEN 'active' THEN 1 WHEN 'paused' THEN 2 ELSE 0 END AS status_code FROM accounts;Simple switch-style caseSELECT region, SUM(CASE WHEN returned = true THEN 1 ELSE 0 END) AS returns, COUNT(*) AS total FROM orders GROUP BY region;Return count vs total per region (conditional pivot)UPDATE products SET tier = CASE WHEN price < 10 THEN 'budget' WHEN price < 50 THEN 'mid' ELSE 'premium' END;Bulk classification update using CASE in SET clauseNesting CASE 4+ levels deep (CASE WHEN … THEN CASE WHEN … THEN CASE …) creates unmaintainable logic that is nearly impossible to debug. Each additional level exponentially increases cognitive load.
✓ Instead: Refactor into a lookup/reference table joined at query time, a PL/pgSQL function, or multiple CTEs that classify data incrementally. For simple NULL substitution, prefer COALESCE over a CASE WHEN col IS NULL THEN default ELSE col END pattern.
Combine CASE with COUNT or SUM to pivot or count conditionally: `SUM(CASE WHEN status = 'paid' THEN amount ELSE 0 END)` counts paid-only totals within a GROUP BY — no subquery needed.
SELECT month, SUM(CASE WHEN type = 'income' THEN amount ELSE 0 END) AS income, SUM(CASE WHEN type = 'expense' THEN amount ELSE 0 END) AS expenses FROM ledger GROUP BY month;Conditional sums per category per month