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 'Unknown'
        WHEN price < 50 THEN 'Budget'
        WHEN price BETWEEN 50 AND 100 THEN 'Standard'
        ELSE 'Premium'
    END AS price_category
FROM products;

Что здесь происходит?

  1. Если цена price у товара не указана NULL, мы отображаем категорию как 'Unknown'.
  2. Если цена меньше 50, товар считается бюджетным 'Budget'.
  3. Если цена находится в диапазоне от 50 до 100, он попадает в категорию 'Standard'.
  4. Всё остальное — это товары премиум-класса 'Premium'.

Вот результат:

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, словно волшебник, читает строки таблицы 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 '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 любезно распределяет студентов, как строгий экзаменатор: 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 'No Status'
        ELSE status
    END AS order_status,
    COUNT(*)
FROM orders
GROUP BY 
    CASE
        WHEN status IS NULL THEN 'No Status'
        ELSE status
    END;

Этот запрос аккуратно обрабатывает пустые статусы NULL и подставляет 'No Status' вместо них, а также подсчитывает общее количество заказов в каждой группе. Вот результат:

order_status count
Completed 3
Pending 2
Shipped 2
No Status 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 'Never Logged In'
        WHEN last_login < CURRENT_DATE - INTERVAL '30 days' THEN 'Inactive'
        ELSE 'Active'
    END AS user_status
FROM users;

С этим запросом система админа оживает: пользователей без входа называют "Never Logged In", а тех, кто давно не заходил, считают "Inactive". Остальные активны!

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

Распространённые ошибки и как их избежать

Пропуск ELSE: Если вы не добавите ELSE, SQL просто вернёт NULL, если ни одно из условий не выполнено. Это не всегда то, что вы хотите. Поэтому лучше явно указывать ELSE, даже если вы уверены, что учли все случаи.

CASE
    WHEN condition THEN result
    -- ELSE 'Default value' -- не забудьте!
END

Сложные условия без скобок: Если у вас несколько сложных условий с AND, OR или NOT, всегда используйте скобки. Без них ваш запрос может начать "думать" неправильно.

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

Работа с NULL: Помните, что NULL никогда не равно (=) чему-либо. Например:

CASE
    WHEN column = NULL THEN 'Nope!' -- Ошибка!
    WHEN column IS NULL THEN 'Correct!' -- Вот это правильно.
END
2
Задача
SQL SELF, 10 уровень, 0 лекция
Недоступна
Условное отображение отсутствующих данных
Условное отображение отсутствующих данных
2
Задача
SQL SELF, 10 уровень, 0 лекция
Недоступна
Присвоение категорий на основе числовых значений
Присвоение категорий на основе числовых значений
Комментарии (2)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Сергей Третяк Уровень 14
22 октября 2025
могли бы и явно указать что проверка на IS NULL должна быть первой
Anemon Уровень 13 Expert
27 августа 2025
🤓