JavaRush /Курси /SQL SELF /Умовні вирази: CASE WHEN ... THEN ... ELSE ... END

Умовні вирази: CASE WHEN ... THEN ... ELSE ... END

SQL SELF
Рівень 10 , Лекція 0
Відкрита

Скоріш за все, ти вже стикався з умовними виразами в мовах програмування: if-else, switch-case та подібними конструкціями. В SQL є свій інструмент для роботи з умовами: це вираз CASE. Він дозволяє приймати рішення прямо в запитах: якщо умова виконується — зробити одне, якщо ні — інше.

Конструкція CASE особливо корисна, коли треба працювати з даними, які можуть містити NULL значення. Синтаксис простий, як шпаргалка, дивись:

CASE
    WHEN умова1 THEN результат1
    WHEN умова2 THEN результат2
    ...
    ELSE результат_за_замовчуванням
END

Логічно, правда? "Якщо так — зроби це, інакше — інше". Запам’ятати легко: "WHEN — це якщо, THEN — що робити, ELSE — що робити, якщо нічого не підійшло".

Приклад: класифікація товарів

Уяви, що у нас є таблиця products, де є колонка 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 'Невідомо'
        WHEN price < 50 THEN 'Бюджетний'
        WHEN price BETWEEN 50 AND 100 THEN 'Стандартний'
        ELSE 'Преміум'
    END AS price_category
FROM products;

Що тут відбувається?

  1. Якщо ціна price у товару не вказана NULL, ми показуємо категорію як 'Невідомо'.
  2. Якщо ціна менше 50, товар вважається бюджетним 'Бюджетний'.
  3. Якщо ціна в діапазоні від 50 до 100, він потрапляє в категорію 'Стандартний'.
  4. Все інше — це товари преміум-класу 'Преміум'.

Ось результат:

product_name price price_category
Magic Wand 120 Преміум
Potion Set 45 Бюджетний
Crystal Ball 75 Стандартний
Enchanted Map NULL Невідомо
Broomstick 99 Стандартний
Spell Book 180 Преміум

SQL, як справжній чарівник, читає рядки таблиці products, застосовує до кожної і хитро класифікує.

Робота з NULL у CASE WHEN

Часто буває, що в даних є пропущені значення (привіт, NULL), і їх треба чимось замінити. Наприклад, у нас є таблиця users з колонкою email, і для користувачів без електронної пошти ми хочемо показати 'Не вказано'.

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 'Не вказано'
        ELSE email
    END AS email_address
FROM users;
user_id name email_address
1 Alex Lin alex@example.com
2 Maria Chi Не вказано
3 Anna Song anna@magic.com
4 Otto Art Не вказано
5 John Smith john@wizard.org

SQL тут працює як шаман, оживляючи напівпорожні рядки. Якщо email відсутній, він підставляє текст 'Не вказано'. Якщо email є — просто залишає його.

Умовні вирази з числами

Іноді треба не просто замінити значення, а й побудувати нову логіку. Наприклад, у нас є таблиця students зі стовпцями score (оцінка) і name.

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

Ми хочемо оцінювати студентів як "Успішний", "Нормальний" і "Неуспішний", залежно від їхніх балів.

SELECT
    name AS student_name,
    score,
    CASE
        WHEN score IS NULL THEN 'Немає оцінки'
        WHEN score >= 90 THEN 'Відмінно'
        WHEN score >= 50 THEN 'Зараховано'
        ELSE 'Не зараховано'
    END AS performance_category
FROM students;
student_name score performance_category
Alex Lin 95 Відмінно
Maria Chi 82 Зараховано
Anna Song 48 Не зараховано
Otto Art NULL Немає оцінки
John Smith 67 Зараховано
Zoe Black 30 Не зараховано

SQL люб’язно розподіляє студентів, як суворий екзаменатор: 90 балів і вище — тільки "Відмінно", від 50 — "Зараховано". А якщо балів не вистачає... ну, ти зрозумів.

Групування і обробка NULL

Робота з групами даних — ще одна сфера, де CASE WHEN блискуче себе показує. Уяви, що у нас є таблиця orders, і ми хочемо порахувати загальну кількість замовлень по статусу, включаючи замовлення зі статусом NULL.

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 'Без статусу'
        ELSE status
    END AS order_status,
    COUNT(*)
FROM orders
GROUP BY 
    CASE
        WHEN status IS NULL THEN 'Без статусу'
        ELSE status
    END;

Цей запит акуратно обробляє порожні статуси NULL і підставляє 'Без статусу' замість них, а також рахує загальну кількість замовлень у кожній групі. Ось результат:

order_status count
Completed 3
Pending 2
Shipped 2
Без статусу 3

Практичні кейси: "Фокуси" з CASE WHEN

Приклад 1: Сортування з урахуванням NULL

Іноді NULL значення треба показувати або першими, або останніми у відсортованому списку. Це часто використовується, наприклад, у списках задач, де пріоритетні задачі мають бути вище, а задачі без пріоритету (NULL) — в кінці.

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;

Тут ми додали "віртуальну" колонку priority_sort, яка ставить NULL значення нижче всіх, а інші сортує за зростанням.

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

Приклад 2: Обчислення з урахуванням NULL

А тепер уяви, що ми рахуємо підсумкову суму замовлення в таблиці orders, де в колонці discount знижка може бути NULL, якщо її немає.

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

Треба замінити NULL на 0, щоб розрахунок не ламався.

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

Цей магічний трюк з CASE дозволяє бути впевненим, що NULL не зламає математику.

Для orderid = 101: discount = 10. finalprice = 100 - 10 = 90. Для orderid = 102: discount = NULL. CASE повертає 0. finalprice = 200 - 0 = 200. Для orderid = 103: discount = 15. finalprice = 150 - 15 = 135. Для orderid = 104: discount = NULL. CASE повертає 0. finalprice = 120 - 0 = 120. Для orderid = 105: discount = 5. finalprice = 80 - 5 = 75.

Приклад 3: Відображення статусів користувачів

У повсякденній роботі часто треба показати статус користувача (наприклад, "Активний" чи "В очікуванні") або вказати на відсутність даних. Наприклад, у таблиці users є колонка 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 'Жодного входу'
        WHEN last_login < CURRENT_DATE - INTERVAL '30 days' THEN 'Неактивний'
        ELSE 'Активний'
    END AS user_status
FROM users;

З цим запитом система адміна оживає: користувачів без входу називають "Жодного входу", а тих, хто давно не заходив — "Неактивний". Інші — активні!

user_id name user_status
1 Alex Lin Неактивний
2 Maria Chi Неактивний
3 Anna Song Жодного входу
4 Otto Art Неактивний
5 Liam Park Активний

Поширені помилки і як їх уникнути

Пропуск ELSE: Якщо ти не додаси ELSE, SQL просто поверне NULL, якщо жодна умова не виконається. Це не завжди те, що ти хочеш. Тому краще явно вказувати ELSE, навіть якщо впевнений, що врахував усе.

CASE
    WHEN condition THEN result
    -- ELSE 'Значення за замовчуванням' -- не забудь!
END

Складні умови без дужок: Якщо у тебе кілька складних умов з AND, OR чи NOT, завжди використовуй дужки. Без них твій запит може "думати" неправильно.

CASE
    WHEN (column1 IS NOT NULL AND column2 > 5) THEN 'Валідно'
    ELSE 'Не валідно'
END

Робота з NULL: Пам’ятай, що NULL ніколи не дорівнює (=) чомусь. Наприклад:

CASE
    WHEN column = NULL THEN 'Ні!' -- Помилка!
    WHEN column IS NULL THEN 'Правильно!' -- Ось це правильно.
END
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ