Условная логика: CASE, COALESCE, NULLIF

CASE добавляет ветвление, COALESCE подставляет запасное значение, NULLIF гасит нежелательное.

CASE — это «if/else» внутри SQL. COALESCE возвращает первый не-NULL аргумент. NULLIF(a, b) возвращает NULL, если a = b (иначе a) — частый приём защиты от деления на ноль.

CASE: ветвление прямо в SELECT

Превратим число в категорию. CASE проверяет условия сверху вниз и возвращает значение первой подошедшей ветки; ELSE ловит остальное.

CREATE TABLE student(name TEXT, score INTEGER);
INSERT INTO student VALUES ('Аня',92),('Борис',74),('Вика',58),('Глеб',40);

SELECT name, score,
       CASE
         WHEN score >= 85 THEN 'отлично'
         WHEN score >= 70 THEN 'хорошо'
         WHEN score >= 50 THEN 'удовл.'
         ELSE 'неуд.'
       END AS grade
FROM student;

Вывод:

name   score  grade
-----  -----  -------
Аня    92     отлично
Борис  74     хорошо
Вика   58     удовл.
Глеб   40     неуд.

Порядок веток важен: 74 подошло бы и под >= 50, но >= 70 стоит выше и срабатывает первым. CASE также удобен внутри агрегатов: SUM(CASE WHEN paid THEN amount ELSE 0 END) — условное суммирование.

COALESCE: запасное значение вместо NULL

NULL означает «нет данных» и портит вывод. COALESCE перебирает аргументы слева направо и возвращает первый не-NULL.

CREATE TABLE contact(name TEXT, phone TEXT, email TEXT);
INSERT INTO contact VALUES
 ('Аня',NULL,'anya@mail'),('Борис','+700',NULL),('Вика',NULL,NULL);

SELECT name,
       COALESCE(phone, email, 'нет данных') AS best_contact
FROM contact;

Вывод:

name   best_contact
-----  ------------
Аня    anya@mail
Борис  +700
Вика   нет данных

У Ани нет телефона → берётся email. У Вики нет ничего → подставляется текст-заглушка. Так строят «лучший доступный контакт» или заменяют NULL нулём в отчётах.

NULLIF: защита от деления на ноль

NULLIF(a, b) возвращает NULL, если значения равны. Главный сценарий — знаменатель: x / NULLIF(y, 0) вместо ошибки/бесконечности даст NULL, когда y = 0.

SELECT 10 / NULLIF(0, 0) AS safe_div;

Вывод:

safe_div
--------

Знаменатель NULLIF(0,0) стал NULL, деление на NULL дало NULL (пустая ячейка) — без аварии. Обернув это в COALESCE(x / NULLIF(y,0), 0), получите аккуратный 0 в отчёте.

Памятка

ФункцияДелает
CASE WHEN ... THEN ... ELSE ... ENDветвление, первое истинное условие выигрывает
COALESCE(a, b, c)первый не-NULL аргумент
NULLIF(a, b)NULL, если a = b; иначе a

Итог

  • CASE — ветвление в SQL; ветки проверяются по порядку, поэтому строгие условия пишут выше.
  • COALESCE заменяет NULL первым доступным значением (контакт «по приоритету», заглушки).
  • NULLIF(y, 0) в знаменателе спасает от деления на ноль — результат станет NULL вместо ошибки.
Проверьте себя
1. В CASE условия score >= 85 и score >= 70 идут в таком порядке. Что вернётся для score = 74?
A'отлично', потому что проверяется первой
B'хорошо', потому что ветки проверяются по порядку и срабатывает первая истинная (>= 70)
CNULL
DОбе ветки сразу
2. Что вернёт COALESCE(NULL, NULL, 'нет данных')?
ANULL
BПустую строку
C'нет данных'
DОшибку
3. Зачем писать x / NULLIF(y, 0)?
AЧтобы округлить результат
BЧтобы при y = 0 знаменатель стал NULL и деление дало NULL вместо ошибки/аварии
CЧтобы ускорить деление
DNULLIF умножает на ноль
Поддержать проект