> SmartGate 41 752 9863

COALESCE

Функция для подстановки значений вместо NULL

Теория

После темы NULL появляется вопрос: что делать, если значение не определено, а в результате запроса всё равно нужно показать что-то понятное?

Представьте ситуацию. Мы хотим вывести список пользователей. Если у человека есть телефон, показываем телефон. Если телефона нет, показываем почту. А если и этого нет, выводим фразу 'контакт не указан'. Это и есть типичная задача для COALESCE.

По сути COALESCE — это как CASE на минималках. Данная функция просто проверяет значения по порядку и берёт первое, которое не равно NULL.

Проговорим действие этой функции: попробуй взять первое значение из значений столбцов, перечисленных в скобках внутри функции; если его нет, возьми следующее; если и его нет, возьми ещё одно; если ничего не нашлось, тогда уже вернётся NULL или то запасное значение, которое вы указали в конце.

Важно: COALESCE ничего не меняет в таблице. Она только помогает показать результат запроса в более удобном виде или подставить запасной вариант вместо неопределённого значения.

Синтаксис

COALESCE(value1, value2, value3, ...)
SQL
Внутри COALESCE(...) значения пишутся по порядку.

Логика такая:
• если первое значение есть, функция вернёт его (речь про значения внутри скобок после COALESCE(...));
• если первое значение равно NULL, проверяется второе;
• если второе тоже NULL, проверяется третье;
• и так далее.

То есть COALESCE всегда пытается взять первое доступное значение.

Например, запись COALESCE(city, 'город не указан') читается так: если город указан, показать его; если нет — вывести текст 'город не указан'.

А если написать COALESCE(phone, email, 'контакт не указан'), смысл будет такой: сначала попробуй взять телефон, если его нет — возьми почту, а если нет ни того ни другого — покажи текст 'контакт не указан').

Есть и важное ограничение: значения внутри COALESCE должны быть совместимы по типу данных. Например, нельзя бездумно смешать число, дату и текст в одной функции. В таких случаях SQL обычно выдаст ошибку. Если очень нужно совместить разные типы, сначала их приводят к одному виду через преобразование типа.

И ещё полезно помнить: весь результат COALESCE(...) можно назвать через псевдоним, как обычный вычисляемый столбец. Например: COALESCE(city, 'город не указан') AS city_label.

Примеры

1. Показываем понятный текст вместо неопределенного города

Если город в строке заполнен, COALESCE вернёт его. Если в city есть NULL, в результате появится текст 'город не указан'.

🔄 Попробуйте изменить запрос:

  • • Замените текст 'город не указан' на 'нет данных'
  • • Отсортируйте результат по вычисляемому столбцу: ORDER BY city_label ASC

2. Подставляем запасной статус для заказов без статуса

Идея та же самая, только уже на другой таблице. Если статус заказа ещё не заполнен, вместо пустого значения пользователь увидит понятную фразу.

🔄 Попробуйте изменить запрос:

  • • Поменяйте текст 'статус не указан' на 'ожидает обработки'
  • • Оставьте только заказы без статуса, добавив условие AND status IS NULL

3. Ищем товары, где категория не указана

В этом примере COALESCE используется не в SELECT, а в WHERE. Если категория у товара не указана, функция временно подставит текст 'без категории', и такую строку можно будет отфильтровать обычным сравнением.

🔄 Попробуйте изменить запрос:

  • • Замените текст 'без категории' на 'категория не указана' и поправьте сравнение ниже
  • • Уберите условие WHERE, а в SELECT добавьте COALESCE(category, 'без категории') AS category_label

4. Сортируем заказы так, чтобы пустой статус не мешал

Этот пример показывает ещё один сценарий применения функции. Если в сортировке участвует поле, где у части строк стоит NULL, можно временно подставить запасное значение и тем самым задать более понятный порядок.

🔄 Попробуйте изменить запрос:

  • • Подставьте вместо 'яяя' текст '---' и посмотрите, как изменится порядок строк
  • • Добавьте в SELECT столбец COALESCE(status, 'статус не указан') AS status_label

5. Подставляем текст вместо цены и заранее приводим тип

Здесь важен не только сам COALESCE, но и приведение типа. Поле price — числовое, а текст 'цена не указана' — строковый. Если написать COALESCE(price, 'цена не указана'), PostgreSQL выдаст ошибку. Поэтому сначала мы переводим цену в текст через price::text, и только потом подставляем запасной вариант.

🔄 Попробуйте изменить запрос:

  • • Уберите ::text у поля price и посмотрите, какая ошибка получится

Типичные ошибки

Думают, что COALESCE заменяет и NULL, и пустую строку
'' — это не NULL. Если в колонке лежит пустая строка, COALESCE её не тронет.

Используют COALESCE там, где достаточно простого IS NULL
Если задача просто найти пустые значения, обычно понятнее написать WHERE column IS NULL. COALESCE полезнее там, где нужно именно подставить запасной вариант.

Забывают, что аргументы проверяются слева направо
COALESCE вернёт первое подходящее значение и дальше уже не пойдёт. Поэтому порядок аргументов здесь важен.

Смешивают несовместимые типы данных
Например, запись вроде COALESCE(price, 'нет цены') может закончиться ошибкой, потому что число и текст — это разные типы. Если нужно такое поведение, сначала стоит явно привести значения к одному типу.

Думают, что COALESCE меняет данные в таблице
Нет, не меняет. Он только вычисляет значение в результате запроса. Сами данные в базе остаются как были.

Практика

Проверь себя

Ответьте на вопросы, чтобы закрепить материал:

1
Что делает COALESCE?
2
Что вернёт выражение COALESCE(NULL, 'резерв', 'ещё один вариант')?
3
Почему выражение COALESCE(price, 'цена не указана') может завершиться ошибкой?
4
Какой вариант правильно показывает, что результату COALESCE(...) можно дать псевдоним?
5
Что вернёт выражение SELECT COALESCE(NULL, NULL, 45);? Введите только значение.
6
Напишите запрос к таблице workers, который выведет worker_id, first_name, salary и столбец salary_label. В salary_label нужно показать зарплату как текст, а если зарплата не указана — вывести 'зарплата не указана'. Оставьте только работников из отдела 2 и отсортируйте результат по worker_id.
7
Что вернёт COALESCE(NULL, NULL, NULL)?
8
Напишите запрос к таблице orders, который выведет order_id, status и столбец status_label. В status_label нужно показать status, а если статус не указан — вывести 'ожидает статуса'. Оставьте только заказы, где worker_id равен 3, и отсортируйте результат по order_id.