All 40 lessons

Lesson 12 of 40 · SQL Functions

SQL CASE WHEN

By Skillancy Editorial Team

Every example runs on the ShopKart dataset, already loaded in the free SQL Compiler. Click Try it in the SQL Compiler under a query to open it there, then press Run.

CASE WHEN adds if-then-else logic to a query. It checks conditions in order and returns the value for the first one that's true. Analysts use it to bucket numbers into bands, turn codes into labels, and count things conditionally.

Syntax

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

There's also a shorter "simple" form for comparing one column to fixed values:

CASE column
  WHEN value1 THEN result1
  WHEN value2 THEN result2
  ELSE default_result
END

Examples

1. Price bands

SELECT product_name,
       price,
       CASE
         WHEN price >= 10000 THEN 'Premium'
         WHEN price >= 2000  THEN 'Mid-range'
         ELSE 'Budget'
       END AS price_band
FROM products
ORDER BY price DESC
LIMIT 8;
Try it in the SQL Compiler

Result:

product_namepriceprice_band
Samsung 43" Smart TV31990.00Premium
Redmi Note 13 Pro23999.00Premium
Women's Silk Saree8499.00Mid-range
Cricket Bat (Kashmir Willow)3499.00Mid-range
Kumkumadi Face Oil2995.00Mid-range
Running Shoes2499.00Mid-range
Prestige Pressure Cooker 5L2199.00Mid-range
Men's Cotton Kurta1899.00Budget

(8 rows)

Because CASE stops at the first true condition, a ₹23,999 phone is labelled Premium and never reaches the Mid-range check.

2. Simple CASE to relabel codes

SELECT order_id,
       payment_method,
       CASE payment_method
         WHEN 'COD' THEN 'Cash on Delivery'
         WHEN 'UPI' THEN 'UPI'
         ELSE 'Online (Card/NetBanking)'
       END AS payment_type
FROM orders
LIMIT 5;
Try it in the SQL Compiler

Result:

order_idpayment_methodpayment_type
1001UPIUPI
1002CardOnline (Card/NetBanking)
1003UPIUPI
1004CardOnline (Card/NetBanking)
1005NetBankingOnline (Card/NetBanking)

(5 rows)

3. Delivery speed

SELECT order_id,
       delivery_date - order_date AS days,
       CASE
         WHEN delivery_date IS NULL THEN 'Not delivered'
         WHEN delivery_date - order_date <= 3 THEN 'Fast'
         ELSE 'Slow'
       END AS delivery_speed
FROM orders
WHERE order_id BETWEEN 1001 AND 1006;
Try it in the SQL Compiler

Result:

order_iddaysdelivery_speed
10013Fast
10025Slow
10033Fast
1004NULLNot delivered
10053Fast
10064Slow

(6 rows)

Check for NULL first; otherwise NULL days would fall through to ELSE 'Slow'.

4. Conditional counts (CASE inside an aggregate)

This is the most powerful use of CASE. Count orders by outcome in a single row:

SELECT COUNT(*) AS total_orders,
       SUM(CASE WHEN status = 'Delivered' THEN 1 ELSE 0 END) AS delivered,
       SUM(CASE WHEN status IN ('Cancelled', 'Returned') THEN 1 ELSE 0 END) AS lost
FROM orders;
Try it in the SQL Compiler

Result:

total_ordersdeliveredlost
24164

(1 row)

This pattern is the basis of pivoting data in SQL.

5. Custom sort order

Sort orders by how urgently they need attention, not alphabetically:

SELECT order_id, status
FROM orders
WHERE status <> 'Delivered'
ORDER BY CASE status
           WHEN 'Pending' THEN 1
           WHEN 'Shipped' THEN 2
           WHEN 'Returned' THEN 3
           ELSE 4
         END,
         order_id;
Try it in the SQL Compiler

Result:

order_idstatus
1023Pending
1024Pending
1020Shipped
1022Shipped
1006Returned
1015Returned
1004Cancelled
1012Cancelled

(8 rows)

Common mistakes

  • Forgetting END. Every CASE must close with END.
  • Wrong condition order. WHEN price >= 2000 before WHEN price >= 10000 labels everything above ₹2,000 as Mid-range.
  • Mixed result types. All THEN values should be the same type. Don't return a number in one branch and text in another.
  • No ELSE. Unmatched rows become NULL, which may be what you want, but it should be deliberate.

Practice question

Label each customer as "Early adopter" if they signed up before 2025, otherwise "New". Show name, signup date and the label.

Show solution
SELECT customer_name,
       signup_date,
       CASE
         WHEN signup_date < '2025-01-01' THEN 'Early adopter'
         ELSE 'New'
       END AS customer_type
FROM customers
ORDER BY signup_date
LIMIT 8;
Try it in the SQL Compiler

Result:

customer_namesignup_datecustomer_type
Aarav Sharma2024-03-15Early adopter
Priya Nair2024-05-22Early adopter
Rohan Gupta2024-07-01Early adopter
Sneha Reddy2024-08-10Early adopter
Vikram Singh2024-09-05Early adopter
Ananya Iyer2024-11-18Early adopter
Karan Mehta2025-01-09New
Ishita Das2025-02-14New

(8 rows)

Key takeaways

  • CASE WHEN ... THEN ... ELSE ... END is SQL's if-then-else.
  • Conditions are checked in order; the first true one wins.
  • Without ELSE, unmatched rows return NULL.
  • SUM(CASE WHEN ... THEN 1 ELSE 0 END) counts rows that meet a condition.

Frequently asked questions

What happens if no WHEN condition matches?

CASE returns the ELSE value. If there is no ELSE, it returns NULL.

Does CASE stop at the first matching condition?

Yes. Conditions are checked top to bottom and the first true one wins, so put the most specific conditions first.

Can I use CASE in WHERE, ORDER BY and GROUP BY?

Yes. CASE is an expression, so it can appear anywhere a value can: SELECT, WHERE, ORDER BY, GROUP BY and inside aggregate functions.

Newsletter

Keep learning SQL

One email a week with SQL and analytics guides, new practice questions and cohort dates. No spam, unsubscribe anytime.

Prefer a one-page summary? Download the free SQL cheat sheet (PDF)