В PostgreSQL для условной логики есть несколько инструментов.
COALESCE — замена NULL и выбор доступного значения
COALESCE возвращает первый аргумент, который не равен NULL. Выражение используют, чтобы задать резервное значение, выбрать заполненное поле или обработать отсутствующие данные при расчёте.
NULL означает отсутствие или неизвестность значения. Это не ноль, не пустая строка и не FALSE: COALESCE пропускает только NULL.
Синтаксис и порядок выбора
COALESCE(value_1, value_2, ...)
Аргументы проверяются слева направо. Возвращается первое значение, отличное от NULL; если все аргументы равны NULL, результат тоже NULL. Приоритет определяется порядком аргументов.
| Выражение | Результат | Пояснение |
coalesce(NULL, 20, 10) |
20 | Первое доступное число |
coalesce(10, 20) |
10 | Первый аргумент уже заполнен |
coalesce(NULL, NULL) |
NULL | Все значения отсутствуют |
coalesce(0, 100) |
0 | Ноль не пропускается |
coalesce('', 'Нет данных') |
'' | Пустая строка не пропускается |
coalesce(FALSE, TRUE) |
FALSE | FALSE не пропускается |
Совместимость типов
Все аргументы должны приводиться к общему типу данных. Он определяется для выражения целиком, а не только по фактически выбранному значению.
SELECT coalesce(42, 'неизвестно');
-- Ошибка преобразования текста в integer
Если результат должен быть текстовым, явно преобразуйте число в text:
SELECT coalesce(42::text, 'неизвестно');
-- Результат: '42'
COALESCE входит в стандарт SQL. В PostgreSQL это специальное условное выражение с синтаксисом вызова функции. Для подстановки вместо NULL оно выполняет задачи, похожие на IFNULL в MySQL.
Расчёты с отсутствующей скидкой
Вычитание NULL из цены даёт NULL. Если по правилам расчёта отсутствующая скидка означает нулевую скидку, замените её через COALESCE. В этом примере скидка задана суммой, а не процентом.
WITH items(product, price, discount) AS ( VALUES ('A', 1200::numeric, 150::numeric), ('B', 800, NULL), ('C', 600, 0))SELECT product, price - discount AS without_fallback, price - coalesce(discount, 0) AS net_priceFROM itemsORDER BY product;
| Товар | Без подстановки | С COALESCE |
| A | 1050 | 1050 |
| B | NULL | 800 |
| C | 600 | 600 |
Для товара B итоговая стоимость равна 800: нулём заменяется скидка, цена сохраняется. Если NULL означает, что скидка ещё не определена, такая подстановка может исказить смысл данных.
Резервное значение из другого столбца
В таблице posts могут быть столбцы excerpt с кратким описанием и content с полным текстом. Если описания нет, можно взять первые 150 символов статьи:
SELECT coalesce(excerpt, left(content, 150), 'Нет описания') AS previewFROM posts;
Сначала выбирается excerpt, затем фрагмент content, затем подпись «Нет описания». Если excerpt содержит пустую строку, она будет выбрана как обычное значение.
Пустые строки и NULLIF
NULLIF(a, b) возвращает NULL, если a равно b, иначе возвращает a. В сочетании с COALESCE оно позволяет считать пустую строку отсутствующим значением:
SELECT coalesce(nullif('', ''), 'Не указано');
-- Результат: 'Не указано'
Если нужно также обработать строки из обычных пробелов, сначала примените TRIM:
SELECT coalesce(nullif(trim(' '), ''), 'Не указано');
-- Результат: 'Не указано'
Нулевой итог при отсутствии данных
SUM возвращает NULL, если входных строк нет или все складываемые значения равны NULL. Если в отчёте в таких случаях нужен ноль, подставьте его после вычисления суммы:
SELECT coalesce(sum(amount), 0) AS totalFROM (VALUES (NULL::numeric)) AS payments(amount);
-- Результат: 0
Положение COALESCE имеет значение. SUM(COALESCE(amount, 0)) заменяет NULL внутри существующих строк, но при полном отсутствии строк результат SUM всё равно будет NULL. COALESCE(SUM(amount), 0) обрабатывает и этот случай.
При GROUP BY отсутствующая группа сама по себе не создаётся: COALESCE заменяет значения, но не добавляет строки результата.
Когда использовать CASE
Для простой подстановки вместо NULL запись с COALESCE короче. Эти выражения дают одинаковый результат:
coalesce(discount, 0)
CASE WHEN discount IS NULL THEN 0 ELSE discountEND
CASE подходит, если выбор зависит от других условий: диапазона суммы, статуса или нескольких проверок. Для проверки отсутствующего значения используется IS NULL, а не = NULL. Универсального преимущества по скорости у одной записи перед другой нет: оно зависит от конкретного запроса.
Что важно учитывать
При выполнении запроса COALESCE вычисляет аргументы только до первого значения, отличного от NULL. Аргументы справа от него не вычисляются. При этом проверка типов относится ко всем аргументам; отдельные постоянные выражения могут обрабатываться ещё при планировании запроса.
COALESCE в SELECT изменяет результат запроса, но не записывает подставленные значения в таблицу. Выбирайте замену по смыслу: нулевая сумма и неизвестная сумма — разные состояния.