Урок доступен в видеоформате 

Условная логика, оператор CASE

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

Что такое условная логика?

Под условной логикой понимается наличие у программы нескольких путей выполнения в зависимости от каких-то условий.

Например, в базе данных «Расписание» есть таблица Student с полем birthday, отражающим дату рождения студента. Допустим, в выборке необходимо отобразить не саму дату рождения, а текстовое значение «Совершеннолетний» или «Несовершеннолетний» в зависимости от того, есть ли студенту 18 лет. Это и есть пример условной логики, при которой должно вывестись либо одно значение, либо другое в зависимости от конкретного условия.

Реализация такого запроса с помощью CASE может выглядеть следующим образом:

MySQL 8.4
SELECT first_name, last_name,
CASE
  WHEN TIMESTAMPDIFF(YEAR, birthday, NOW()) >= 18 THEN 'Совершеннолетний'
  ELSE 'Несовершеннолетний'
END AS status
FROM Student
MySQL 8.4
SELECT first_name, last_name,
CASE
  WHEN EXTRACT(YEAR FROM AGE(NOW(), birthday)) >= 18 THEN 'Совершеннолетний'
  ELSE 'Несовершеннолетний'
END AS status
FROM Student
first_namelast_namestatus
NikolajSokolovСовершеннолетний
VyacheslavEliseevСовершеннолетний
IvanEfremovСовершеннолетний
AnatolijZHdanovНесовершеннолетний
GeorgijNoskovСовершеннолетний
ArtyomSergeevНесовершеннолетний
ArinaEvseevaСовершеннолетний
AngelinaVoroncovaСовершеннолетний
EkaterinaUstinovaСовершеннолетний
RaisaLapinaСовершеннолетний
LeonidIgnatovНесовершеннолетний
SnezhanaSeliverstovaСовершеннолетний
SemyonBiryukovСовершеннолетний
GeorgijBaranovСовершеннолетний
YUliyaVishnyakovaСовершеннолетний
ValentinaBolshakovaСовершеннолетний
LeonidKryukovСовершеннолетний
VladislavCvetkovСовершеннолетний
SnezhanaMorozovaСовершеннолетний
LyubovBorisovaСовершеннолетний
AnfisaKalashnikovaСовершеннолетний
AnnaOsipovaСовершеннолетний

Синтаксис поискового выражения CASE

MySQL 8.4
CASE
    WHEN условие THEN результат
    [WHEN ...]
    [ELSE результат_по_умолчанию]
END
  • [ ]необязательная часть
  • ...можно повторить
условие
Логическое выражение ветки WHEN, например price > 100.
результат

Значение, которое вернёт CASE, если условие ветки истинно.

результат_по_умолчанию

Значение на случай, когда ни одно условие не выполнено. Без ELSE вернётся NULL.

Необязательный

Ветки WHEN проверяются по порядку: если условие первой ветки истинно, выражение CASE вернёт её результат, иначе будет сделана проверка следующей ветки и т. д.

Пример

Рассмотрим оператор CASE на примере определения этапа школьного образования.

Этапы школьного образования

MySQL 8.4
SELECT 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.4
SELECT 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
namestage
8 AСредняя школа
8 BСредняя школа
9 CСредняя школа
9 BСредняя школа
9 AСредняя школа
10 BСтаршая школа
10 AСтаршая школа
11 BСтаршая школа
11 AСтаршая школа
7 AСредняя школа
7 BСредняя школа
6 AСредняя школа
6 BСредняя школа
5 AСредняя школа
5 BСредняя школа
4 AНачальная школа
  • Сначала мы извлекаем номер класса из его названия
    MySQL 8.4
    SUBSTRING(name, 1, INSTR(name, ' '))
    
  • Сначала мы извлекаем номер класса из его названия
    MySQL 8.4
    SUBSTRING(name, 1, POSITION(' ' IN name) - 1)
    
  • Далее мы проверяем вхождение данного номера в список классов, относящихся к «Старшая школа» и «Средняя школа».
  • Если номер класса не находится в диапазоне 5–11, мы выводим «Начальная школа».

Синтаксис простого выражения CASE

Оператор CASE также имеет и более простой синтаксис, который схож с поисковым выражением CASE, но является менее гибким. Так он выглядит в общем виде:

MySQL 8.4
CASE значение
    WHEN сравниваемое_значение THEN результат
    [WHEN ...]
    [ELSE результат_по_умолчанию]
END
  • [ ]необязательная часть
  • ...можно повторить
значение
Выражение, которое проверяется, например столбец таблицы.
сравниваемое_значение

Конкретное значение ветки WHEN, например число или строка.

результат

Значение, которое вернёт CASE, если значение совпало со значением ветки.

результат_по_умолчанию

Значение на случай, когда совпадений нет. Без ELSE вернётся NULL.

Необязательный

В этом синтаксисе значение в CASE поочерёдно сравнивается с переданными значениями в WHEN и при совпадении возвращается значение, следующее за THEN.

Используя этот синтаксис, можно переписать наш предыдущий пример таким образом:

MySQL 8.4
SELECT 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.4
SELECT 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
namestage
8 AСредняя школа
8 BСредняя школа
9 CСредняя школа
9 BСредняя школа
9 AСредняя школа
10 BСтаршая школа
10 AСтаршая школа
11 BСтаршая школа
11 AСтаршая школа
7 AСредняя школа
7 BСредняя школа
6 AСредняя школа
6 BСредняя школа
5 AСредняя школа
5 BСредняя школа
4 AНачальная школа

Проверьте себя

Какое значение вернёт оператор CASE в данном случае?

MySQL 8.4
CASE 2
  WHEN 0 THEN 'Ноль'
  WHEN 1 THEN 'Один'
  ELSE 'Много'
END