> SmartGate 41 752 9863

CASE

Условная логика внутри SQL-запроса

Теория

Представьте обычную ситуацию. В таблице лежит зарплата в виде числа: 65000, 90000, 120000. Но нам захотелось посмотреть не просто на числа, а на понятные категории: 'базовая', 'средняя', 'высокая'. Или, например, в таблице у части пользователей город не указан, и в результате хочется показать не пустое значение, а фразу 'город не указан'.

Существует интересная конструкция, ее еще часто называют условной, называется она CASE. Она позволяет добавить в запрос условную логику: если для строки выполняется одно условие — вернуть одно значение, если другое — вернуть другое.

Можно думать о CASE как о маленьком наборе правил прямо внутри запроса. SQL берёт строку, проверяет её по этим правилам и возвращает результат, который вы хотите получить, если для строки правило выполняется.

Важно: CASE ничего не меняет в таблице, а только показывает данные в более удобном виде в результате SELECT или помогает задать свою логику сортировки в ORDER BY или выполняет гибкие вычисления.

Синтаксис

CASE
    WHEN condition THEN result
    WHEN condition THEN result
    ELSE result
END
SQL
Идея такая:
• после WHEN пишется условие, которое нужно проверить;
• после THEN пишется значение, которое нужно получить, если условие выполнилось;
ELSE — это запасной вариант на случай, если ни одно условие выше не выполнилось.

CASE проверяет условия сверху вниз. Как только для текущей строки подошло первое условие, SQL сразу берёт значение из этого THEN и дальше уже не идёт.

Поэтому порядок веток очень важен. Сначала обычно ставят более точные или более приоритетные условия, а потом уже всё остальное. Или условие четко определяют нижней и верхней границей через AND.

Если ELSE не написать, то для строк, которые не попали ни под одно условие, результатом будет NULL. Иногда это нормально, но чаще удобнее сразу явно указать, что вернуть по умолчанию.

Важно: весь CASE ... END можно назвать через псевдоним так же, как обычный вычисляемый столбец. Именно поэтому в примерах ниже после END стоит AS new_salary, AS city_label или AS status_label.

Примеры

1. Считаем новую зарплату по разным правилам повышения

Здесь при помощи CASE мы считаем новое числовое значение. Если зарплата меньше 70000, она увеличивается на 20%. Если попадает в диапазон от 70000 до 99999, повышается на 10%. Для остальных строк остаётся как есть.

🔄 Попробуйте изменить запрос:

  • • Поменяйте границу 70000 на 80000 и посмотрите, кому теперь попадёт повышение 20%
  • • Сделайте повышение для средней группы не на 10%, а на 15%: salary * 1.15

2. Показываем вместо пустого города понятный текст

Если город указан, показываем его как есть. Если города нет, вместо пустого значения выводим понятный текст. Для интерфейсов и отчётов это часто удобнее.

🔄 Попробуйте изменить запрос:

  • • Замените текст 'город не указан' на 'нет данных'
  • • Отсортируйте результат по вычисляемому столбцу: ORDER BY city_label ASC

3. Расшифровываем статусы заказов в более человеческий вид

Еще один интересный сценарий для CASE: категоризовать значения по более понятным и удобным формулировкам.

🔄 Попробуйте изменить запрос:

  • • Сделайте для 'доставлен' отдельную подпись, убрав его из IN
  • • Поменяйте текст 'Статус не указан' на 'Ожидает обработки'

4. Сортируем пользователей по своему правилу

Обычно ORDER BY city просто сортирует по алфавиту. Но иногда нужен свой порядок. Здесь мы сами задаём приоритет: сначала Москва, потом Алматы, потом остальные города, а строки без города уходят в конец.

🔄 Попробуйте изменить запрос:

  • • Поставьте строки без города в начало, изменив число у ветки WHEN city IS NULL
  • • Поменяйте местами приоритеты для 'Москва' и 'Алматы'

Типичные ошибки

Ставят условия в неудачном порядке
CASE идёт сверху вниз. Если верхнее условие уже подходит строке, остальные условия ниже для этой строки уже не проверяются. Поэтому сначала лучше ставить более точные условия, а потом более общие.

Забывают про ELSE
Если ни одно условие не подошло, а ELSE нет, результатом будет NULL. Иногда это нормально, но чаще пользователь просто увидит пустое значение и не поймёт, почему так произошло. Вместо ELSE можно также указать еще одну ветку THEN, в которой указать все остальные случаи.

Пытаются обрабатывать NULL как обычное значение
Если нужно отдельно поймать пустое значение, надёжнее писать WHEN column IS NULL THEN .... Это понятнее и работает предсказуемо.

Думают, что CASE меняет данные в таблице
Нет, не меняет. Он только вычисляет значение в результате запроса. В самой таблице ничего не переписывается.

Практика

Проверь себя

Ответьте на вопросы, чтобы закрепить материал:

1
Что вернёт CASE, если ни одно условие не подошло, а ELSE не указан?
2
Почему в конструкции ниже порядок веток важен?
CASE WHEN price >= 50000 THEN 'дорогой' WHEN price >= 100000 THEN 'премиум' ELSE 'обычный' END
3
Напишите запрос, который выведет product_id, product_name, price и новый столбец price_group из таблицы products. Логика такая: если цена меньше 50000'бюджетный', если цена от 50000 до 99999'средний', иначе — 'премиум'.
4
Какой вариант правильно показывает, что всей конструкции CASE ... END можно дать псевдоним?
5
Напишите запрос, который выведет worker_id, first_name, salary и столбец salary_label из таблицы workers. Логика такая: если зарплата не указана — вернуть 'не указана', если зарплата меньше 80000 — вернуть 'ниже 80000', иначе — '80000 и выше'. Результат отсортируйте по дате найма от более ранних к более поздним.
6
Что вернёт выражение CASE WHEN 10 > 20 THEN 1 ELSE 0 END? Введите только число.
7
Напишите запрос, который выведет product_id, product_name, category и price из таблицы products, а сортировка должна работать по такому правилу: сначала товары категории 'Смартфоны', потом 'Ноутбуки', потом товары без категории, а после них — все остальные. Внутри каждой группы более дорогие товары должны идти выше.