SQL CASE WHEN Multiple Conditions Guide
Most candidates think CASE WHEN evaluates all conditions and picks the best match. It doesn't. It walks the WHEN list top to bottom and stops at the first TRUE. That one detail is why half the CASE WHEN answers we see in mock interviews bucket rows into the wrong tier. The interviewer isn't checking whether you know the keyword. They're checking whether you know the order of evaluation.
Know CASE WHEN the way the interviewer who asks it knows it.
CASE WHEN Syntax Review
-- General syntax with multiple conditions
CASE
WHEN condition1 AND condition2 THEN result_a
WHEN condition3 OR condition4 THEN result_b
WHEN condition5 THEN result_c
ELSE default_result
END
-- Searched CASE (most flexible)
SELECT
CASE
WHEN age_bucket = '65+' AND account_status = 'inactive' THEN 'Senior Discount'
WHEN age_bucket = '18-24' OR account_status = 'student' THEN 'Student Rate'
ELSE 'Standard Rate'
END AS pricing_tier
FROM users;
-- Simple CASE (equality only, no AND/OR)
SELECT
CASE account_status
WHEN 'active' THEN 'Active'
WHEN 'inactive' THEN 'Inactive'
WHEN 'pending' THEN 'Pending'
ELSE 'Unknown'
END AS status_label
FROM users;Nth Highest Salary Per Department
> For each department, find the employee with the third-highest salary. If a department has fewer than 3 employees, exclude it. Return department, employee name, and their salary.
5 CASE WHEN Patterns
Multiple WHEN Clauses (Sequential Evaluation)
CASE evaluates WHEN clauses from top to bottom and returns the result for the first condition that is TRUE. Once a match is found, remaining clauses are skipped. This means the order of your WHEN clauses matters. Put the most specific or most restrictive conditions first. The ELSE clause handles any rows that do not match any WHEN condition.
-- Categorize transactions by size
SELECT
transaction_id,
total_amount,
CASE
WHEN total_amount >= 10000 THEN 'Enterprise'
WHEN total_amount >= 1000 THEN 'Mid-Market'
WHEN total_amount >= 100 THEN 'Small Business'
ELSE 'Micro'
END AS order_tier
FROM transactions;
-- Order matters: a $15,000 transaction matches the first clause
-- and is labeled 'Enterprise'. The second clause is never
-- checked for that row, even though $15,000 >= 1000 is true.CASE WHEN with AND (Multiple Conditions per Clause)
AND combines multiple conditions within a single WHEN clause. All conditions must be TRUE for the clause to match. This pattern handles business rules that depend on two or more factors simultaneously: an order is 'Priority' only if the amount is high AND the customer is VIP. Both conditions must hold.
-- Flag high-value orders from premium accounts for expedited shipping
SELECT
t.transaction_id,
u.account_status,
t.total_amount,
CASE
WHEN u.account_status = 'premium' AND t.total_amount >= 5000
THEN 'Priority Ship'
WHEN u.account_status = 'premium' AND t.total_amount < 5000
THEN 'Standard Ship'
WHEN t.total_amount >= 5000
THEN 'Expedited Ship'
ELSE 'Standard Ship'
END AS shipping_tier
FROM transactions t
JOIN users u ON u.user_id = t.user_id;
-- Row with premium + $8,000: matches first clause
-- Row with premium + $200: matches second clause
-- Row with regular + $6,000: matches third clause
-- Row with regular + $50: falls to ELSECASE WHEN with OR (Alternative Conditions)
OR allows a single WHEN clause to match any of several conditions. The clause fires if at least one condition is TRUE. Use OR when multiple distinct scenarios should produce the same result. This reduces duplication compared to writing separate WHEN clauses that all return the same value.
-- Identify accounts needing review
SELECT
user_id,
account_status,
signup_date,
CASE
WHEN account_status = 'closed' OR account_status = 'suspended'
THEN 'Immediate Review'
WHEN account_status = 'inactive' OR signup_date < '2020-01-01'
THEN 'Routine Review'
ELSE 'No Action'
END AS review_action
FROM users;
-- Closed OR suspended status: same action needed
-- Inactive OR signed up before 2020: same review tierNested CASE Expressions
A CASE expression can appear inside another CASE expression. The outer CASE handles the first decision. The inner CASE refines the result based on additional criteria. This pattern is useful when the logic has a natural hierarchy: first determine the category, then within that category determine the subcategory. Keep nesting to two levels maximum; deeper nesting becomes unreadable.
-- Tiered pricing based on account type and volume
SELECT
oi.user_id,
u.account_status,
oi.quantity,
oi.unit_price,
CASE
WHEN u.account_status = 'premium' THEN
CASE
WHEN oi.quantity >= 1000 THEN oi.unit_price * 0.70
WHEN oi.quantity >= 100 THEN oi.unit_price * 0.85
ELSE oi.unit_price * 0.90
END
WHEN u.account_status = 'active' THEN
CASE
WHEN oi.quantity >= 500 THEN oi.unit_price * 0.90
ELSE oi.unit_price * 0.95
END
ELSE oi.unit_price
END AS final_price
FROM order_items oi
JOIN users u ON u.user_id = oi.user_id;CASE WHEN Inside Aggregate Functions
Placing CASE WHEN inside COUNT, SUM, or AVG creates conditional aggregation. This computes different metrics from the same rows in a single pass. It replaces multiple filtered subqueries and is one of the most powerful reporting patterns in SQL. Combined with GROUP BY, it produces cross-tabulation reports.
-- Single query: multiple conditional metrics
SELECT
department,
COUNT(*) AS total_employees,
COUNT(CASE WHEN salary >= 100000 THEN 1 END) AS high_earners,
SUM(CASE WHEN manager_id IS NOT NULL THEN salary ELSE 0 END) AS reports_payroll,
AVG(CASE
WHEN hire_date < '2020-01-01' AND salary >= 90000
THEN salary
END) AS avg_salary_senior_performers
FROM employees
GROUP BY department;
-- COUNT(CASE...) counts only rows where the condition is true
-- NULL results from unmatched CASE are ignored by COUNT
-- SUM uses ELSE 0 to avoid NULL in the sumCommon CASE WHEN Pitfalls
Pitfall 1: Wrong WHEN clause order with overlapping conditions
- CASE short-circuits on the first match. If a broad condition appears before a specific one, the specific clause never fires.
- Fix: Put the most specific (restrictive) conditions first.
Pitfall 2: Missing NULL handling
- WHEN column = 'value' does not match rows where column is NULL. NULL = anything is UNKNOWN, not FALSE. These rows fall through all WHEN clauses and hit ELSE (or become NULL if there is no ELSE).
- Fix: Add WHEN column IS NULL THEN 'default' as an explicit clause, or use COALESCE(column, 'fallback') before the comparison.
Pitfall 3: No ELSE clause when NULL is not acceptable
- Without ELSE, CASE returns NULL when no WHEN matches. If the result feeds into arithmetic (NULL + 5 = NULL) or a WHERE filter (NULL is not TRUE), downstream logic breaks silently.
- Fix: Always include ELSE unless you deliberately want NULL for unmatched rows. For conditional aggregation (COUNT(CASE...)), omitting ELSE is intentional because COUNT ignores NULLs.
3 CASE WHEN Interview Questions
Q1: Write a CASE expression that categorizes customers into risk tiers based on multiple factors: account age, balance, and transaction frequency.
What they test: Ability to combine multiple conditions with AND/OR inside WHEN clauses. The interviewer wants to see you handle a multi-factor decision tree cleanly. They also check whether you order your WHEN clauses correctly (most restrictive first) and include an ELSE for the default case. Approach: Define the tiers clearly before writing SQL. High risk: balance < 0 OR (account_age < 30 AND transaction_count = 0). Medium risk: balance < 500 AND transaction_count < 5. Low risk: everything else. Write the CASE with the most critical conditions first. Explain that order matters because CASE short-circuits on the first match. Add ELSE 'Low Risk' as the catch-all.
Q2: Rewrite a query that uses multiple LEFT JOINs to count different order statuses into a single query using CASE WHEN inside COUNT.
What they test: Whether you understand conditional aggregation as an alternative to multiple joins or subqueries. This tests both CASE WHEN proficiency and query optimization awareness. Conditional aggregation scans the table once instead of joining it multiple times. Approach: Show the before (three LEFT JOINs to subqueries counting pending, shipped, and cancelled orders) and the after (single GROUP BY with COUNT(CASE WHEN status = 'pending' THEN 1 END) for each status). Explain that the CASE returns NULL for non-matching rows and COUNT ignores NULLs, so each COUNT only tallies the matching status. Mention the performance benefit: one table scan vs three.
Q3: A CASE expression returns unexpected NULL values for some rows. All WHEN conditions look correct. What is the problem?
What they test: Understanding of CASE default behavior and NULL comparison pitfalls. When no WHEN clause matches and there is no ELSE, CASE returns NULL. Also, WHEN column = value does not match when column is NULL because NULL = anything is UNKNOWN, not TRUE. Approach: Two common causes. First: missing ELSE clause. If no WHEN matches, CASE returns NULL. Always add an ELSE unless you intentionally want NULL. Second: NULL input values. WHEN status = 'active' does not match rows where status IS NULL. To handle NULLs, add a specific clause: WHEN status IS NULL THEN 'Unknown'. Or use COALESCE on the input: WHEN COALESCE(status, 'unknown') = 'active'.
Frequently asked questions
How do I use multiple conditions in a SQL CASE WHEN?+
What is the difference between multiple WHEN clauses and AND conditions?+
Can I nest CASE expressions inside each other?+
The interviewer isn't testing syntax
- 01
Active recall beats re-reading by 50%
Cognitive-science meta-reviews (Dunlosky et al., 2013) rank practice testing as a top-tier study technique, while re-reading and highlighting rank near the bottom
- 02
76% of hiring managers reject on the coding task, not the resume
From HackerRank's 2024 Developer Skills Report. Candidates who look strong on paper still fail the live screen if they haven't done timed, executable practice
- 03
Five problem shapes cover 80% of data engineer loops
Dedup, sessionization, top-N-per-group, slowly-changing dimensions, partition tricks. Writing the shapes by hand turns the unfamiliar into pattern recognition