CodeGym /Courses /SQL SELF /Conditional Expressions: CASE WHEN ... THEN ... ELSE ... ...

Conditional Expressions: CASE WHEN ... THEN ... ELSE ... END

SQL SELF
Level 10 , Lesson 0
Available

Chances are, you’ve already seen conditional expressions in programming languages: if-else, switch-case, and stuff like that. SQL has its own tool for working with conditions: the CASE expression. It lets you make decisions right in your queries: if a condition is true, do one thing; if not, do something else.

The CASE construct is especially handy when you’re dealing with data that might have NULL values. The syntax is super simple, like a cheat sheet—check it out:

CASE
    WHEN condition1 THEN result1
    WHEN condition2 THEN result2
    ...
    ELSE default_result
END

Makes sense, right? "If it’s like this, do that, otherwise do something else." Easy to remember: "WHEN is if, THEN is what to do, ELSE is what to do if nothing matched."

Example: Classifying Products

Imagine we have a products table with a price column, and we want to group products based on their price.

id name price
1 Magic Wand 120
2 Potion Set 45
3 Crystal Ball 75
4 Enchanted Map NULL
5 Broomstick 99
6 Spell Book 180
SELECT
    name AS product_name,
    price,
    CASE
        WHEN price IS NULL THEN 'Unknown'
        WHEN price < 50 THEN 'Budget'
        WHEN price BETWEEN 50 AND 100 THEN 'Standard'
        ELSE 'Premium'
    END AS price_category
FROM products;

What’s going on here?

  1. If the product’s price is missing (NULL), we show the category as 'Unknown'.
  2. If the price is less than 50, the product is considered 'Budget'.
  3. If the price is between 50 and 100, it goes into the 'Standard' category.
  4. Everything else is a premium product 'Premium'.

Here’s the result:

product_name price price_category
Magic Wand 120 Premium
Potion Set 45 Budget
Crystal Ball 75 Standard
Enchanted Map NULL Unknown
Broomstick 99 Standard
Spell Book 180 Premium

SQL is like a wizard here, reading each row from the products table and cleverly classifying them.

Working with NULL in CASE WHEN

It’s super common to have missing values in your data (hey there, NULL), and you’ll want to swap them out for something else. For example, let’s say we have a users table with an email column, and for users without an email, we want to show 'Not Provided'.

user_id name email
1 Alex Lin alex@example.com
2 Maria Chi NULL
3 Anna Song anna@magic.com
4 Otto Art NULL
5 John Smith john@wizard.org
SELECT
    user_id,
    name,
    CASE
        WHEN email IS NULL THEN 'Not Provided'
        ELSE email
    END AS email_address
FROM users;
user_id name email_address
1 Alex Lin alex@example.com
2 Maria Chi Not Provided
3 Anna Song anna@magic.com
4 Otto Art Not Provided
5 John Smith john@wizard.org

SQL here works like a shaman, bringing half-empty rows to life. If the email is missing, it swaps in 'Not Provided'. If there’s an email—it just leaves it as is.

Conditional Expressions with Numbers

Sometimes you need more than just swapping values—you want to build new logic. For example, let’s say we have a students table with score and name columns.

name score
Alex Lin 95
Maria Chi 82
Anna Song 48
Otto Art NULL
John Smith 67
Zoe Black 30

We want to grade students as "Excellent", "Pass", and "Fail" depending on their scores.

SELECT
    name AS student_name,
    score,
    CASE
        WHEN score IS NULL THEN 'No Score'
        WHEN score >= 90 THEN 'Excellent'
        WHEN score >= 50 THEN 'Pass'
        ELSE 'Fail'
    END AS performance_category
FROM students;
student_name score performance_category
Alex Lin 95 Excellent
Maria Chi 82 Pass
Anna Song 48 Fail
Otto Art NULL No Score
John Smith 67 Pass
Zoe Black 30 Fail

SQL kindly sorts the students like a strict examiner: 90 and up is "Excellent", 50 and up is "Pass". If you don’t have enough points... well, you get the idea.

Grouping and Handling NULL

Working with groups of data is another area where CASE WHEN really shines. Imagine we have an orders table, and we want to count the total number of orders by status, including orders with a NULL status.

order_id status
1 Completed
2 Pending
3 NULL
4 Shipped
5 Completed
6 NULL
7 Pending
8 Completed
9 Shipped
10 NULL
SELECT
    CASE
        WHEN status IS NULL THEN 'No Status'
        ELSE status
    END AS order_status,
    COUNT(*)
FROM orders
GROUP BY 
    CASE
        WHEN status IS NULL THEN 'No Status'
        ELSE status
    END;

This query neatly handles empty NULL statuses and swaps in 'No Status' instead, then counts the total orders in each group. Here’s the result:

order_status count
Completed 3
Pending 2
Shipped 2
No Status 3

Practical Cases: "Magic Tricks" with CASE WHEN

Example 1: Sorting with NULL Handling

Sometimes you want NULL values to show up either first or last in a sorted list. This is common, for example, in task lists where high-priority tasks should be at the top, and tasks with no priority (NULL) should be at the bottom.

task_id task_name priority
1 Fix bugs 1
2 Update documentation 3
3 Plan sprint NULL
4 Code review 2
5 Organize meeting NULL
6 Deploy release 1
SELECT
    task_name,
    priority,
    CASE
        WHEN priority IS NULL THEN 1
        ELSE 0
    END AS priority_sort
FROM tasks
ORDER BY priority_sort ASC, priority ASC;

Here we added a "virtual" column priority_sort that puts NULL values at the bottom, and sorts the rest in ascending order.

task_name priority priority_sort
Deploy release 1 0
Fix bugs 1 0
Code review 2 0
Update documentation 3 0
Plan sprint NULL 1
Organize meeting NULL 1

Example 2: Calculations with NULL Handling

Now imagine we’re calculating the final order total in the orders table, where the discount column might be NULL if there’s no discount.

order_id total_price discount
101 100 10
102 200 NULL
103 150 15
104 120 NULL
105 80 5

We need to swap NULL for 0 so the calculation doesn’t break.

SELECT 
    order_id,
    total_price,
    discount,
    total_price - 
    CASE
        WHEN discount IS NULL THEN 0
        ELSE discount
    END AS final_price
FROM orders;
order_id total_price discount final_price
101 100 10 90
102 200 NULL 200
103 150 15 135
104 120 NULL 120
105 80 5 75

This magic trick with CASE makes sure NULL doesn’t mess up your math.

For order_id = 101: discount = 10, final_price = 100 − 10 = 90. For order_id = 102: discount = NULL, CASE returns 0, final_price = 200 − 0 = 200. For order_id = 103: discount = 15, final_price = 150 − 15 = 135. For order_id = 104: discount = NULL, CASE returns 0, final_price = 120 − 0 = 120. For order_id = 105: discount = 5, final_price = 80 − 5 = 75.

Example 3: Showing User Statuses

In everyday work, you’ll often need to show a user’s status (like "Active" or "Pending") or point out missing data. For example, in the users table, there’s a last_login column with the date of the last login.

user_id name last_login
1 Alex Lin 2024-12-10
2 Maria Chi 2025-04-20
3 Anna Song NULL
4 Otto Art 2025-05-01
5 Liam Park 2025-05-25
SELECT
    user_id,
    name,
    CASE
        WHEN last_login IS NULL THEN 'Never Logged In'
        WHEN last_login < CURRENT_DATE - INTERVAL '30 days' THEN 'Inactive'
        ELSE 'Active'
    END AS user_status
FROM users;

With this query, the admin system comes alive: users who never logged in are called "Never Logged In", and those who haven’t logged in for a while are "Inactive". The rest are active!

user_id name user_status
1 Alex Lin Inactive
2 Maria Chi Inactive
3 Anna Song Never Logged In
4 Otto Art Inactive
5 Liam Park Active

Common Mistakes and How to Avoid Them

Forgetting ELSE: If you don’t add ELSE, SQL will just return NULL if none of the conditions match. That’s not always what you want. So it’s better to always specify ELSE, even if you think you’ve covered all the cases.

CASE
    WHEN condition THEN result
    -- ELSE 'Default value' -- don’t forget!
END

Complex conditions without parentheses: If you have several complex conditions with AND, OR, or NOT, always use parentheses. Without them, your query might start "thinking" wrong.

CASE
    WHEN (column1 IS NOT NULL AND column2 > 5) THEN 'Valid'
    ELSE 'Invalid'
END

Working with NULL: Remember, NULL is never equal (=) to anything. For example:

CASE
    WHEN column = NULL THEN 'Nope!' -- Wrong!
    WHEN column IS NULL THEN 'Correct!' -- This is right.
END
2
Task
SQL SELF, level 10, lesson 0
Locked
Conditional Display of Missing Data
Conditional Display of Missing Data
2
Task
SQL SELF, level 10, lesson 0
Locked
Assigning Categories Based on Numeric Values
Assigning Categories Based on Numeric Values
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION