Условная логика, оператор CASE
SQL, подобно многим языкам программирования, позволяет писать условную логику, чтобы в зависимости от набора условий возвращать одно из множества возможных значений. В этой статье мы рассмотрим, как это реализуется в SQL с помощью оператора CASE.
Что такое условная логика?
Под условной логикой понимается наличие у программы нескольких путей выполнения в зависимости от каких-то условий.
Например, в базе данных «Расписание» есть таблица Student с полем birthday, отражающим дату рождения студента. Допустим, в выборке необходимо отобразить не саму дату рождения, а текстовое значение «Совершеннолетний» или «Несовершеннолетний» в зависимости от того, есть ли студенту 18 лет. Это и есть пример условной логики, при которой должно вывестись либо одно значение, либо другое в зависимости от конкретного условия.
Реализация такого запроса с помощью CASE может выглядеть следующим образом:
MySQL 8.4SELECT first_name, last_name, CASE WHEN TIMESTAMPDIFF(YEAR, birthday, NOW()) >= 18 THEN 'Совершеннолетний' ELSE 'Несовершеннолетний' END AS status FROM Student
MySQL 8.4SELECT first_name, last_name, CASE WHEN EXTRACT(YEAR FROM AGE(NOW(), birthday)) >= 18 THEN 'Совершеннолетний' ELSE 'Несовершеннолетний' END AS status FROM Student
Синтаксис поискового выражения CASE
CASE
WHEN условие THEN результат
[WHEN ...]
[ELSE результат_по_умолчанию]
END- [ ]необязательная часть
- ...можно повторить
- условие
- Логическое выражение ветки WHEN, например price > 100.
- результат
Значение, которое вернёт CASE, если условие ветки истинно.
- результат_по_умолчанию
Значение на случай, когда ни одно условие не выполнено. Без ELSE вернётся NULL.
Необязательный
Ветки WHEN проверяются по порядку: если условие первой ветки истинно, выражение CASE вернёт её результат, иначе будет сделана проверка следующей ветки и т. д.
Пример
Рассмотрим оператор CASE на примере определения этапа школьного образования.

MySQL 8.4SELECT name, CASE WHEN SUBSTRING(name, 1, INSTR(name, ' ')) IN (10, 11) THEN 'Старшая школа' WHEN SUBSTRING(name, 1, INSTR(name, ' ')) IN (5, 6, 7, 8, 9) THEN 'Средняя школа' ELSE 'Начальная школа' END AS stage FROM Class
MySQL 8.4SELECT name, CASE WHEN SUBSTRING(name, 1, POSITION(' ' IN name) - 1) IN ('10', '11') THEN 'Старшая школа' WHEN SUBSTRING(name, 1, POSITION(' ' IN name) - 1) IN ('5', '6', '7', '8', '9') THEN 'Средняя школа' ELSE 'Начальная школа' END AS stage FROM Class
- Сначала мы извлекаем номер класса из его названия
MySQL 8.4
SUBSTRING(name, 1, INSTR(name, ' '))
- Сначала мы извлекаем номер класса из его названия
MySQL 8.4
SUBSTRING(name, 1, POSITION(' ' IN name) - 1)
- Далее мы проверяем вхождение данного номера в список классов, относящихся к «Старшая школа» и «Средняя школа».
- Если номер класса не находится в диапазоне 5–11, мы выводим «Начальная школа».
Синтаксис простого выражения CASE
Оператор CASE также имеет и более простой синтаксис, который схож с поисковым выражением CASE, но является менее гибким. Так он выглядит в общем виде:
CASE значение
WHEN сравниваемое_значение THEN результат
[WHEN ...]
[ELSE результат_по_умолчанию]
END- [ ]необязательная часть
- ...можно повторить
- значение
- Выражение, которое проверяется, например столбец таблицы.
- сравниваемое_значение
Конкретное значение ветки WHEN, например число или строка.
- результат
Значение, которое вернёт CASE, если значение совпало со значением ветки.
- результат_по_умолчанию
Значение на случай, когда совпадений нет. Без ELSE вернётся NULL.
Необязательный
В этом синтаксисе значение в CASE поочерёдно сравнивается с переданными значениями в WHEN и при совпадении возвращается значение, следующее за THEN.
Используя этот синтаксис, можно переписать наш предыдущий пример таким образом:
MySQL 8.4SELECT name, CASE SUBSTRING(name, 1, INSTR(name, ' ')) WHEN 11 THEN 'Старшая школа' WHEN 10 THEN 'Старшая школа' WHEN 9 THEN 'Средняя школа' WHEN 8 THEN 'Средняя школа' WHEN 7 THEN 'Средняя школа' WHEN 6 THEN 'Средняя школа' WHEN 5 THEN 'Средняя школа' ELSE 'Начальная школа' END AS stage FROM Class
MySQL 8.4SELECT name, CASE SUBSTRING(name, 1, POSITION(' ' IN name) - 1) WHEN '11' THEN 'Старшая школа' WHEN '10' THEN 'Старшая школа' WHEN '9' THEN 'Средняя школа' WHEN '8' THEN 'Средняя школа' WHEN '7' THEN 'Средняя школа' WHEN '6' THEN 'Средняя школа' WHEN '5' THEN 'Средняя школа' ELSE 'Начальная школа' END AS stage FROM Class
Проверьте себя
Какое значение вернёт оператор CASE в данном случае?
MySQL 8.4CASE 2 WHEN 0 THEN 'Ноль' WHEN 1 THEN 'Один' ELSE 'Много' END