COALESCE в SQL возвращает первый из своих аргументов, который не равен NULL. Аргументы проверяются слева направо: COALESCE(telegram, phone, email, 'нет контакта') вернёт телеграм, если он заполнен, иначе телефон, иначе почту, а если пусто всё, то строку «нет контакта». Когда NULL все аргументы, результат тоже NULL.
Функция входит в стандарт SQL и одинаково пишется в PostgreSQL, MySQL, SQL Server, Oracle и SQLite. Ниже синтаксис, примеры с выводом, связка с NULLIF и разница с ISNULL, IFNULL и NVL. Если путаетесь, чем NULL отличается от пустой строки, начните с разбора NULL в SQL.
Синтаксис COALESCE и как она работает

COALESCE(выражение1, выражение2, ..., выражениеN)
Порядок вычисления такой:
- СУБД берёт первый аргумент. Если он не NULL, это и есть ответ.
- Если NULL, переходит ко второму, потом к третьему.
- Первый непустой аргумент возвращается, остальные правее него в PostgreSQL и Oracle даже не вычисляются.
- Если NULL оказались все, функция возвращает NULL.
Самый короткий пример, по образцу из справки Microsoft. Вывод здесь и ниже показан в формате MySQL. В PostgreSQL и SQLite значения те же, а где они расходятся, это сказано отдельно.
SELECT COALESCE(NULL, NULL, 'третье', 'четвёртое') AS result;
+--------+
| result |
+--------+
| третье |
+--------+
Справка PostgreSQL прямо говорит, что аргументы правее первого непустого не вычисляются, Oracle называет то же самое short-circuit evaluation. На практике это значит, что тяжёлое выражение в конце списка не тормозит запрос, пока до него не дошла очередь.
По сути COALESCE служит короткой записью выражения CASE. SQL Server так её и выполняет: оптимизатор переписывает вызов в CASE WHEN выражение1 IS NOT NULL THEN выражение1 ... END, это описано в справке по Transact-SQL. Русская версия этой страницы, кстати, называется «СЛИЯНИЕ», хотя в запросе пишется всё равно COALESCE.
Пример на таблице: подставляем значение вместо NULL
Возьмём таблицу клиентов, где у каждого заполнен свой набор контактов:
CREATE TABLE clients (id INT, name VARCHAR(50), telegram VARCHAR(50), phone VARCHAR(20), email VARCHAR(50));
INSERT INTO clients VALUES
(1, 'Анна', '@anna_k', NULL, 'anna@mail.ru'),
(2, 'Борис', NULL, '+7 900 111-22-33', NULL),
(3, 'Вера', NULL, ' ', 'vera@yandex.ru'),
(4, 'Глеб', NULL, NULL, NULL);
Нужен один столбец «как связаться» с приоритетом телеграм → телефон → почта:
SELECT name, COALESCE(telegram, phone, email, 'нет контакта') AS contact
FROM clients
ORDER BY id;
+-------+------------------+
| name | contact |
+-------+------------------+
| Анна | @anna_k |
| Борис | +7 900 111-22-33 |
| Вера | |
| Глеб | нет контакта |
+-------+------------------+
Анна и Борис получили первый заполненный контакт, Глеб получил значение по умолчанию. А у Веры пусто, хотя почта есть. Причина в том, что телефон у неё записан двумя пробелами: для COALESCE это обычная строка, и до почты очередь не дошла. Как это лечится, показано в разделе про NULLIF ниже.
Канал основателя Checkroi Вани Буявца3 700 человек читают мой Телеграм-канал про нейросетиСобрал промпты для Claude Code и ChatGPT, разборы ИИ-инструментов и лайфхаки по продвижению бизнеса в одном местеПрисоединитьсяCOALESCE с SUM, AVG и в расчётах
SUM, AVG и MAX на пустом наборе строк возвращают NULL. Чаще всего это вылезает в LEFT JOIN, когда у строки слева нет пары справа:
CREATE TABLE orders (client_id INT, amount INT);
INSERT INTO orders VALUES (1, 1500), (1, 2300), (2, 900);
SELECT c.name,
SUM(o.amount) AS raw_sum,
COALESCE(SUM(o.amount), 0) AS total
FROM clients c
LEFT JOIN orders o ON o.client_id = c.id
GROUP BY c.id, c.name
ORDER BY c.id;
+-------+---------+-------+
| name | raw_sum | total |
+-------+---------+-------+
| Анна | 3800 | 3800 |
| Борис | 900 | 900 |
| Вера | NULL | 0 |
| Глеб | NULL | 0 |
+-------+---------+-------+
В отчёте ноль читается как «заказов не было», а пустая ячейка выглядит как «данных нет» или сбой выгрузки. Поэтому сумму по LEFT JOIN обычно оборачивают в COALESCE. С функцией COUNT этого делать не нужно: на пустой группе она сама вернёт 0.
То же правило работает в арифметике. price * NULL даёт NULL, поэтому скидку, которой может не быть, пишут так: price - COALESCE(discount, 0).
NULLIF и COALESCE вместе
NULLIF делает обратную операцию: NULLIF(a, b) возвращает NULL, если a равно b, и a во всех остальных случаях. Вдвоём эти функции решают две частые задачи.
Пустые строки и пробелы
Вернёмся к Вере. Обрезаем пробелы, пустую строку превращаем в NULL, а NULL заменяем текстом:
SELECT name, COALESCE(NULLIF(TRIM(phone), ''), 'не указан') AS phone
FROM clients
ORDER BY id;
+-------+------------------+
| name | phone |
+-------+------------------+
| Анна | не указан |
| Борис | +7 900 111-22-33 |
| Вера | не указан |
| Глеб | не указан |
+-------+------------------+
Деление на ноль
Если делитель может быть нулём, NULLIF превращает его в NULL. Деление на NULL даёт NULL вместо ошибки, а COALESCE подставляет понятный результат:
SELECT 100 / NULLIF(0, 0) AS ratio,
COALESCE(100 / NULLIF(0, 0), 0) AS ratio_safe;
+-------+------------+
| ratio | ratio_safe |
+-------+------------+
| NULL | 0.0000 |
+-------+------------+
PostgreSQL и SQLite на этом запросе показывают в ratio_safe просто 0.
COALESCE, ISNULL, IFNULL и NVL: чем отличаются

У каждой СУБД есть своя функция на два аргумента, которая делает почти то же самое. Разница в типе результата и в поведении на краевых случаях.
| Функция | Где работает | Аргументов | Что важно знать |
|---|---|---|---|
COALESCE |
везде | любое число (в Oracle и SQLite не меньше двух) | стандарт SQL, тип результата берётся самый «старший» из аргументов |
ISNULL(a, b) |
SQL Server | 2 | тип результата берётся у первого аргумента, длинная замена обрезается |
IFNULL(a, b) |
MySQL, SQLite | 2 | в MySQL тип результата берётся более общий из двух |
NVL(a, b) |
Oracle | 2 | при разных типах Oracle неявно приводит один к другому, а если не может, выдаёт ошибку |
ISNULL(a) |
MySQL | 1 | это проверка, а не замена: вернёт 1 или 0 |
В PostgreSQL нет ни ISNULL, ни IFNULL, ни NVL: на SELECT IFNULL(NULL, 1) PostgreSQL 17 отвечает function ifnull(unknown, integer) does not exist. Замену NULL там делают через COALESCE. По справке PostgreSQL, COALESCE даёт возможности, похожие на NVL и IFNULL из других СУБД.
COALESCE и ISNULL в SQL Server
Microsoft перечисляет пять различий между ними. Их стоит знать каждому SQL-разработчику, который пишет процедуры под SQL Server:
- Число вычислений. ISNULL — функция, она вычисляется один раз. Аргументы COALESCE могут вычисляться несколько раз, потому что выражение переписано в CASE.
- Тип результата. ISNULL берёт тип первого параметра, а COALESCE выбирает тип с наивысшим приоритетом среди всех аргументов.
- Допустимость NULL.
ISNULL(col, 0)считается выражением NOT NULL, поэтому вычисляемый столбец с ним может стать первичным ключом. СCOALESCE(col, 0)такой ключ создать не получится. Как объявлять таблицы и ключи в SQL Server, показано в статье о создании базы данных. - Нетипизированный NULL. В ISNULL литерал NULL превращается в
int, а для COALESCE хотя бы одно значение должно иметь тип. - Количество аргументов. У ISNULL их ровно два, у COALESCE сколько угодно.
Из второго пункта вытекает ловушка с обрезкой строк. В справке по ISNULL сказано, что значение замены «может усекаться, если значение replacement_value длиннее, чем check_expression». Если проверяемый столбец объявлен как VARCHAR(5), а замена длиннее, в результат может попасть только её начало. Поэтому для строк с разной длиной надёжнее COALESCE или явный CAST.
Частые ошибки с COALESCE

Разные типы аргументов
Хотим вывести «нет оценки» вместо пустой оценки, где score хранится целым числом:
CREATE TABLE ratings (course VARCHAR(20), score INT);
INSERT INTO ratings VALUES ('SQL', 5), ('SQL', 4), ('SQL', NULL), ('SQL', NULL);
SELECT score, COALESCE(score, 'нет оценки') AS score_text FROM ratings;
MySQL и SQLite молча вернут смешанный столбец. PostgreSQL 17 останавливает запрос с ошибкой:
invalid input syntax for type integer: "нет оценки"
Решение: привести число к строке явно.
-- PostgreSQL, SQL Server
SELECT score, COALESCE(CAST(score AS VARCHAR(10)), 'нет оценки') AS score_text FROM ratings;
-- MySQL: CAST AS VARCHAR там даёт синтаксическую ошибку, нужен CHAR
SELECT score, COALESCE(CAST(score AS CHAR), 'нет оценки') AS score_text FROM ratings;
+-------+------------+
| score | score_text |
+-------+------------+
| 5 | 5 |
| 4 | 4 |
| NULL | нет оценки |
| NULL | нет оценки |
+-------+------------+
Ноль вместо NULL ломает среднее
AVG пропускает NULL. Если заменить их нулями, курс без оценок будет выглядеть как курс с плохими оценками:
SELECT AVG(score) AS avg_real,
AVG(COALESCE(score, 0)) AS avg_zero
FROM ratings; -- оценки: 5, 4, NULL, NULL
+----------+----------+
| avg_real | avg_zero |
+----------+----------+
| 4.5000 | 2.2500 |
+----------+----------+
Правило простое: COALESCE подставляет значение для показа и для сумм. В среднем, минимуме и медиане NULL лучше оставить как есть.
Пустая строка вместо NULL
Симптом: в списке «как связаться» пустые ячейки, хотя запасные контакты есть. Причина та же, что у Веры: в PostgreSQL, MySQL и SQLite пустая строка и пробелы считаются обычными значениями. Решение: COALESCE(NULLIF(TRIM(phone), ''), ...).
ISNULL из SQL Server в MySQL
Запрос ISNULL(phone, 'не указан'), перенесённый из SQL Server, в MySQL падает с ошибкой Incorrect parameter count in the call to native function 'ISNULL'.
В MySQL ISNULL(expr) принимает один аргумент и отвечает 1 или 0, так написано в справочнике операторов сравнения.
Решение: замену там делают через IFNULL (см. функции управления потоком) или COALESCE, и COALESCE удобнее: тот же запрос заработает и в PostgreSQL.
Подзапрос внутри COALESCE в SQL Server
В COALESCE((SELECT ...), 1) подзапрос вычисляется дважды. По справке Microsoft, при уровне изоляции READ COMMITTED в многопользовательской среде такой код может вернуть NULL. Там же три выхода: уровень SNAPSHOT ISOLATION, замена COALESCE на ISNULL или перенос подзапроса во вложенный SELECT, который проверяют уже через CASE.
Где освоить SQL системно
COALESCE встречается почти в каждом отчётном запросе, но это одна функция из многих. Дальше обычно идут оконные функции, подзапросы и оптимизация. Если хотите освоить язык целиком, а не по одной функции, сравните курсы по SQL в подборке ниже.
- начать с основ можно с нашего обзора языка SQL;
- для смены профессии пригодится план, как стать SQL-разработчиком;
- все программы по теме собраны в каталоге курсов SQL.
| Курс | Школа | Стоимость со скидкой | В рассрочку | Длительность | Обзор курса от Checkroi |
|---|---|---|---|---|---|
| Нейросети для рабочих задач Перейти на сайт курса | 31 290 ₽ | - | 1 месяц | Обзор курса | |
| SQL для анализа данных Перейти на сайт курса | 52 353 ₽ | 6203 ₽/мес. | 2 месяца | Обзор курса | |
| SQL-разработчик: тариф PRO Перейти на сайт курса | 89 900 ₽ | 7491 ₽/мес. | 2 месяца | Обзор курса | |
| SQL-разработчик: тариф Базовый Перейти на сайт курса | 79 900 ₽ | 3329 ₽/мес. | 3 месяца | Обзор курса | |
| SQL с нуля | 134 640 ₽ | 5500 ₽/мес. | 12 месяцев | Обзор курса |
Больше программ — в полном каталоге курсов по SQL




