Conditional Functions
SQL offers several tools for expressing conditional logic inside a query — computing a value that depends on other values in the same row. This page pulls the main options together, recaps where each one fits, and flags which ones are portable across database systems and which are not.
CASE: the general-purpose tool
CASE is the standard, ANSI SQL way to express if/then/else logic, and it works identically across every major database. It comes in two forms: a searched CASE (a list of independent boolean conditions) and a simple CASE (comparing one expression against several possible values).
-- Searched CASE
SELECT
order_id,
amount,
CASE
WHEN amount >= 1000 THEN 'Large'
WHEN amount >= 100 THEN 'Medium'
ELSE 'Small'
END AS order_size
FROM orders;
-- Simple CASE
SELECT
status_code,
CASE status_code
WHEN 1 THEN 'Pending'
WHEN 2 THEN 'Shipped'
WHEN 3 THEN 'Delivered'
ELSE 'Unknown'
END AS status_label
FROM shipments;Because CASE can express any conditional logic and runs the same way on every database, it should be the default choice whenever conditional logic is needed inside a SELECT list, an ORDER BY, or even a WHERE clause.
COALESCE and NULLIF
COALESCE(a, b, c, ...) returns the first non-NULL value from its argument list — commonly used to substitute a default when a column might be NULL. NULLIF(a, b) returns NULL if a equals b, and a otherwise — commonly used to turn a sentinel value (like an empty string or a placeholder 0) into a true NULL before further processing. Both are covered in depth on their own page; here they are worth remembering as siblings of CASE, since both can be rewritten using CASE if needed:
-- COALESCE(discount, 0) is equivalent to: CASE WHEN discount IS NOT NULL THEN discount ELSE 0 END -- NULLIF(count, 0) is equivalent to: CASE WHEN count = 0 THEN NULL ELSE count END
Dialect-specific shortcuts
Several databases provide shorthand functions that compress a simple two-way CASE into a single call. These are convenient but not part of the ANSI SQL standard.
Function | Dialect | Equivalent CASE |
|---|---|---|
IF(condition, true_val, false_val) | MySQL, MariaDB, SQLite (as a function) | CASE WHEN condition THEN true_val ELSE false_val END |
IIF(condition, true_val, false_val) | SQL Server | CASE WHEN condition THEN true_val ELSE false_val END |
DECODE(expr, val1, res1, ..., default) | Oracle | Simple CASE with an ELSE default |
Combining CASE with aggregates
A particularly powerful pattern is nesting CASE inside an aggregate function to build conditional counts and sums — effectively a manual pivot table:
SELECT department, COUNT(CASE WHEN status = 'active' THEN 1 END) AS active_count, COUNT(CASE WHEN status = 'inactive' THEN 1 END) AS inactive_count, SUM(CASE WHEN status = 'active' THEN salary ELSE 0 END) AS active_payroll FROM employees GROUP BY department;
Here, CASE returns NULL for rows that don't match the condition, and COUNT() ignores NULLs, so each COUNT(CASE ...) only counts the rows that satisfy its own condition — all within a single pass over the table.