Ever wished you could add if-then-else logic directly in your SQL queries? That's exactly what the CASE statement does. It's like the if statement in programming, but for SQL.
Whether you're categorizing customers, calculating dynamic pricing, or transforming data on the fly, CASE statements are an essential tool in your SQL toolkit.
What is a CASE Statement?
A CASE statement allows you to perform conditional logic within a SQL query. It evaluates a series of conditions and returns a value when the first condition is met.
Think of it as SQL's version of:
if (condition1) {
return value1;
} else if (condition2) {
return value2;
} else {
return defaultValue;
}
Two Types of CASE Statements
SQL supports two forms of CASE: Simple CASE and Searched CASE.
Simple CASE
Compares an expression to a set of simple values:
SELECT
product_name,
CASE category
WHEN 'Electronics' THEN 'Tech'
WHEN 'Clothing' THEN 'Fashion'
WHEN 'Food' THEN 'Grocery'
ELSE 'Other'
END AS department
FROM products;
Searched CASE
Evaluates a set of boolean expressions (more flexible):
SELECT
product_name,
price,
CASE
WHEN price < 10 THEN 'Budget'
WHEN price BETWEEN 10 AND 50 THEN 'Mid-Range'
WHEN price > 50 THEN 'Premium'
ELSE 'Unknown'
END AS price_tier
FROM products;
Which to use? Use Simple CASE for equality checks, Searched CASE for complex conditions.
Real-World Example: Customer Segmentation
Let's say you run an e-commerce site and want to segment customers based on their total spending:
Try it yourself! Modify the thresholds to create different tier structures.
Using CASE in Different Contexts
1. In SELECT Clause (Data Transformation)
Transform values on the fly:
SELECT
order_id,
status,
CASE status
WHEN 'pending' THEN '⏳ Pending'
WHEN 'shipped' THEN '📦 Shipped'
WHEN 'delivered' THEN '✅ Delivered'
WHEN 'cancelled' THEN '❌ Cancelled'
END AS status_display
FROM orders;
2. In WHERE Clause (Dynamic Filtering)
SELECT * FROM products
WHERE
CASE
WHEN @filter_type = 'expensive' THEN price > 100
WHEN @filter_type = 'cheap' THEN price < 20
ELSE 1=1 -- Show all
END;
3. In ORDER BY Clause (Custom Sorting)
Sort by priority instead of alphabetically:
SELECT task_name, priority
FROM tasks
ORDER BY
CASE priority
WHEN 'urgent' THEN 1
WHEN 'high' THEN 2
WHEN 'medium' THEN 3
WHEN 'low' THEN 4
END;
4. In Aggregations (Conditional Counting)
Count different categories in a single query:
Pro tip: This is called "pivoting" and is incredibly useful for reports!
Advanced Pattern: Nested CASE Statements
You can nest CASE statements for complex logic:
SELECT
product_name,
stock_quantity,
CASE
WHEN stock_quantity = 0 THEN 'Out of Stock'
WHEN stock_quantity < 10 THEN
CASE
WHEN reorder_pending THEN 'Low Stock (Reorder Pending)'
ELSE 'Low Stock (Action Required)'
END
WHEN stock_quantity < 50 THEN 'Moderate Stock'
ELSE 'Well Stocked'
END AS inventory_status
FROM inventory;
Warning: Too many nested CASE statements can hurt readability. Consider breaking complex logic into multiple queries or using a lookup table.
Common Pitfalls and How to Avoid Them
Pitfall 1: Forgetting the ELSE Clause
-- ❌ Bad: Returns NULL for unmatched cases
CASE status
WHEN 'active' THEN 'Active'
WHEN 'inactive' THEN 'Inactive'
END
-- ✅ Good: Always include ELSE
CASE status
WHEN 'active' THEN 'Active'
WHEN 'inactive' THEN 'Inactive'
ELSE 'Unknown'
END
Pitfall 2: Type Mismatches
All THEN clauses must return the same data type:
-- ❌ Bad: Mixing numbers and strings
CASE
WHEN age < 18 THEN 'Minor'
WHEN age >= 18 THEN 18 -- Type mismatch!
END
-- ✅ Good: Consistent types
CASE
WHEN age < 18 THEN 'Minor'
WHEN age >= 18 THEN 'Adult'
END
Pitfall 3: Order Matters!
CASE evaluates conditions top-to-bottom and stops at the first match:
-- ❌ Bad: The second condition will never be reached
CASE
WHEN price > 0 THEN 'Has Price'
WHEN price > 100 THEN 'Expensive' -- Never reached!
END
-- ✅ Good: Most specific conditions first
CASE
WHEN price > 100 THEN 'Expensive'
WHEN price > 0 THEN 'Has Price'
END
Performance Considerations
CASE statements are generally fast, but keep these tips in mind:
- Avoid CASE in WHERE clauses on indexed columns - It can prevent index usage
- Use Simple CASE when possible - It's slightly faster than Searched CASE
- Consider computed columns - For frequently used CASE logic, create a computed/generated column
-- Instead of this in every query:
SELECT
CASE WHEN price > 100 THEN 'Expensive' ELSE 'Affordable' END
FROM products;
-- Create a computed column (PostgreSQL example):
ALTER TABLE products
ADD COLUMN price_category TEXT
GENERATED ALWAYS AS (
CASE WHEN price > 100 THEN 'Expensive' ELSE 'Affordable' END
) STORED;
Best Practices
- Always include an ELSE clause - Avoid unexpected NULLs
- Keep it readable - If you have more than 5 conditions, consider a lookup table
- Use meaningful aliases -
AS price_tieris better thanAS col1 - Test edge cases - What happens with NULL values?
- Document complex logic - Add comments for business rules
CASE vs Other Approaches
CASE vs IF Function (MySQL)
MySQL has an IF() function that's simpler for binary conditions:
-- CASE approach
SELECT CASE WHEN age >= 18 THEN 'Adult' ELSE 'Minor' END
-- IF approach (MySQL only)
SELECT IF(age >= 18, 'Adult', 'Minor')
Use IF() for simple binary logic, CASE for multiple conditions.
CASE vs Lookup Tables
For static mappings, a lookup table might be better:
-- Instead of:
CASE country_code
WHEN 'US' THEN 'United States'
WHEN 'UK' THEN 'United Kingdom'
WHEN 'CA' THEN 'Canada'
-- ... 200 more countries
END
-- Use a join:
SELECT c.country_code, cl.country_name
FROM customers c
JOIN country_lookup cl ON c.country_code = cl.code;
Rule of thumb: If you have more than 10 conditions, use a lookup table.
Interactive Challenge
Try to solve this: Create a query that categorizes products based on both price AND rating:
- Premium: price > 50 AND rating >= 4
- Good Value: price <= 50 AND rating >= 4
- Overpriced: price > 50 AND rating < 4
- Budget: Everything else
Conclusion
CASE statements are one of SQL's most versatile features. They let you:
- Transform data on the fly without changing the source
- Implement complex business logic directly in queries
- Create dynamic reports and categorizations
- Handle edge cases gracefully
Key Takeaways:
- Use Simple CASE for equality checks, Searched CASE for complex conditions
- Always include an ELSE clause to avoid NULLs
- Order your conditions from most specific to least specific
- Consider lookup tables for static mappings with many values
- Test your CASE logic with edge cases (NULLs, boundary values)
Now go add some logic to your queries! Try using CASE in your next report or data transformation task.
Test Your Skills with a Real Interview Question
Ready to apply CASE WHEN in a production scenario? Try this Stripe interview question:
Payment Success Rate by Country (Stripe) - Calculate payment success rates using CASE WHEN for conditional counting combined with GROUP BY and HAVING clauses. This question tests your ability to use CASE WHEN within aggregate functions—a critical skill for metrics calculation.
Related Articles
- Mastering SQL Joins: An Interactive Guide - Combine CASE with JOINs for powerful data transformations
- Mastering GROUP BY in SQL - Use CASE with GROUP BY for advanced aggregations
- SQL Subqueries Explained - Nest CASE statements within subqueries