Условные выражения CASE WHEN, COALESCE, NULLIF

Условные выражения SQL: CASE WHEN, COALESCE, NULLIF — ветвление внутри запроса без хранимых процедур и обработка NULL.

Условные выражения позволяют принимать решения прямо внутри SQL-запроса: назначать метки, заменять NULL, делить данные на категории.

CASE WHEN — ветвление

Синтаксис похож на if–else: перебираем условия, возвращаем первое истинное:

SELECT
  emp_name,
  salary,
  CASE
    WHEN salary >= 8000 THEN 'Senior'
    WHEN salary >= 6000 THEN 'Middle'
    ELSE 'Junior'
  END AS grade
FROM employees
ORDER BY salary DESC;

Результат:

emp_name     | salary | grade
-------------+--------+-------
Sarah Connor | 8000   | Senior
Rick Deckard | 7200   | Middle
Tony Montana | 6500   | Middle
Martin Blank | 5600   | Junior
Ethan Hunt   | 5000   | Junior

CASE с агрегатами — условный COUNT

Мощный приём: считать строки только при выполнении условия:

-- Сколько сотрудников в каждой грейд-группе
SELECT
  CASE
    WHEN salary >= 8000 THEN 'Senior'
    WHEN salary >= 6000 THEN 'Middle'
    ELSE 'Junior'
  END AS grade,
  COUNT(*) AS cnt
FROM employees
GROUP BY grade
ORDER BY cnt DESC;

Результат:

grade  | cnt
-------+----
Junior | 2
Middle | 2
Senior | 1

COALESCE — замена NULL

COALESCE(a, b, c, ...) возвращает первый аргумент, который не NULL:

-- Если отдел не назначен — показать 'Unassigned'
SELECT
  emp_name,
  COALESCE(CAST(dept_id AS TEXT), 'Unassigned') AS department
FROM employees;

Результат:

emp_name     | department
-------------+-----------
Ethan Hunt   | 4
Tony Montana | 1
Sarah Connor | 5
Rick Deckard | 3
Martin Blank | Unassigned

COALESCE с двумя столбцами

Полезно, когда значение может быть в одном из нескольких столбцов:

-- Берём city, а если NULL — postal_code
SELECT
  cust_name,
  COALESCE(city, postal_code, 'Unknown') AS location
FROM customers
LIMIT 4;

Результат:

cust_name        | location
-----------------+---------
Maria Anders     | Berlin
Fran Wilson      | Madrid
Dominique Perrier| Paris
Martin Blank     | Turin

NULLIF — обратное COALESCE

NULLIF(a, b) возвращает NULL, если a = b, иначе возвращает a. Часто используется, чтобы избежать деления на ноль:

-- Пример: делим salary на dept_id
-- dept_id может быть NULL, а NULLIF защищает от деления на 0
SELECT
  emp_name,
  salary,
  dept_id,
  ROUND(salary * 1.0 / NULLIF(dept_id, 0), 1) AS ratio
FROM employees;

Результат:

emp_name     | salary | dept_id | ratio
-------------+--------+---------+-------
Ethan Hunt   | 5000   | 4       | 1250.0
Tony Montana | 6500   | 1       | 6500.0
Sarah Connor | 8000   | 5       | 1600.0
Rick Deckard | 7200   | 3       | 2400.0
Martin Blank | 5600   | NULL    | NULL

Когда dept_id равен NULL (или был бы 0), NULLIF возвращает NULL, и результат деления тоже NULL — вместо ошибки.

Коротко

  • CASE WHEN ... THEN ... ELSE ... END — ветвление внутри SELECT; работает и в ORDER BY, и внутри агрегатов.
  • COALESCE(a, b) возвращает первый не-NULL аргумент — удобно заменять NULL на значение по умолчанию.
  • NULLIF(a, b) возвращает NULL при равенстве — защита от деления на ноль и «пустых» строк.
Проверьте себя
1. Где в запросе можно использовать CASE WHEN?
AТолько в SELECT
BВ SELECT, ORDER BY и WHERE
CВ SELECT, ORDER BY, WHERE, GROUP BY и HAVING
DТолько во WHERE
2. Что вернёт COALESCE(NULL, NULL, 42, 100)?
ANULL
B42
C100
DОшибку
3. Зачем нужен NULLIF(x, 0) в выражении деления?
AЧтобы заменить 0 на NULL и избежать ошибки деления на ноль
BЧтобы вернуть 0 вместо NULL
CЧтобы проверить, равен ли x нулю
DЧтобы округлить результат деления
Поддержать проект