> SmartGate

COALESCE

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

Теория

Что делать, если в некоторых строках нужного столбца присутствуют значения NULL, а хочется обработать столбец так, чтобы вместо NULL в результате выдавалось что-то определенное, например какой-то текст или число или еще что-нибудь отличное от NULL?
В принципе, в прошлой теме мы изучили конструкцию CASE, которая хорошо подойдет для такого рода задач, но значения NULL так часто встречаются в таблицах и появляются в результате других операций, таких как соединение таблиц, что использовать везде для их замены конструкцию CASE может оказаться сложноватым.

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

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

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

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

Синтаксис

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

Логика работы следующая:

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

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

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

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

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

Примеры

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • • Уберите ::text у поля price и посмотрите, что произойдет

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

Думают, что COALESCE заменяет и NULL, и пустую строку '' — это не NULL. Если в колонке лежит пустая строка, COALESCE её не тронет. Используют COALESCE там, где достаточно простого IS NULL Если задача просто найти пустые значения, обычно понятнее написать WHERE column IS NULL. COALESCE полезнее там, где нужно именно подставить запасной вариант. Забывают, что аргументы проверяются слева направо COALESCE вернёт первое подходящее значение и дальше уже не пойдёт. Поэтому порядок аргументов здесь важен. Смешивают несовместимые типы данных Например, запись вроде COALESCE(price, 'нет цены') может закончиться ошибкой, потому что число и текст — это разные типы. Если нужно такое поведение, сначала стоит явно привести значения к одному типу.

Практика

Проверь себя

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

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.