К статье
Практический материал

Разработка и Конфигурация · 9 мин

Как работает ЕСТЬNULL в запросе 1С

Разбираем, как работает функция ЕСТЬNULL в запросах 1С: синтаксис, примеры, отличия от ISNULL, типичные ошибки и влияние на производительность запросов.

Функция ЕСТЬNULL в языке запросов 1С подставляет значение по умолчанию вместо NULL. Она нужна везде, где в запросе участвуют левые соединения, необязательные реквизиты или поля, которые могут быть не заполнены: без обработки NULL сравнения, арифметика и группировки ведут себя неочевидно, и отчёт выдаёт неверные цифры.

NULL в 1С — это не пустая строка и не ноль, а отсутствие значения. Любая операция с NULL возвращает NULL: NULL + 5 = NULL, сравнение NULL = 0 даёт ложь, а NULL = NULL тоже не является истиной. Поэтому неотфильтрованные NULL «теряют» строки в условиях и ломают итоги.

Типичный сценарий — левое соединение справочника с регистром остатков: для товаров без движений количество придёт как NULL. Если вывести его напрямую, пользователь увидит пустоту, а суммирование по такой колонке может дать неожиданный результат. ЕСТЬNULL решает задачу одной обёрткой.

Синтаксис и базовые примеры

Функция принимает два аргумента: проверяемое выражение и значение, которое подставляется вместо NULL. Оба аргумента должны быть сравнимы по типу — иначе получите ошибку запроса или неявные проблемы при выводе.

ЕСТЬNULL(Остатки.Количество, 0) КАК Количество

Если Остатки.Количество содержит число — вернётся оно. Если соединение не нашло записи и поле равно NULL — вернётся 0. Аналогично работает подстановка для строк, дат и ссылок:

ЕСТЬNULL(Контрагенты.Телефон, "не указан") КАК Телефон,

ЕСТЬNULL(Заказы.ДатаОтгрузки, ДАТАВРЕМЯ(1,1,1)) КАК ДатаОтгрузки,

ЕСТЬNULL(Товары.СтавкаНДС, ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.БезНДС)) КАК Ставка

Для ссылочных типов в качестве замены обычно используют пустую ссылку через ЗНАЧЕНИЕ, для дат — пустую дату ДАТАВРЕМЯ(1,1,1), для строк — пустую строку или осмысленный текст-заглушку.

bsl
ВЫБРАТЬ
	Товары.Ссылка КАК Товар,
	ЕСТЬNULL(Остатки.Количество, 0) КАК Остаток
ИЗ
	Справочник.Номенклатура КАК Товары
		ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки
		ПО Товары.Ссылка = Остатки.Номенклатура

Почему NULL появляется в запросах

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

Второй источник — составные типы и необязательные реквизиты. Если поле в таблице не заполнено, запрос вернёт NULL. Это касается и полей через точку: обращение Документ.Контрагент.ИНН для документа без контрагента даст NULL, причём «по цепочке» точек NULL распространяется на всё выражение.

Третий случай — итоги и группировки. Агрегатные функции по пустому набору записей и некоторые конструкции с ОБЪЕДИНИТЬ тоже способны дать NULL в результате.

Левое соединениеНет пары в правой таблице

Проверить поля присоединяемой таблицы

Незаполненный реквизитПоле не содержит значения

Посмотреть данные объекта напрямую

Разыменование через точкуРодительское поле пустое

Проверить каждое звено цепочки

ОБЪЕДИНИТЬРазный состав полей в частях

Сверить списки полей всех запросов

ЕСТЬNULL в условиях и соединениях

Без обработки NULL условие отбора ведёт себя контринтуитивно. Запрос ГДЕ Остатки.Количество > 0 отбросит не только нулевые, но и NULL-строки — товары без движений просто исчезнут из результата. Если нужно показать и их, условие пишут через ЕСТЬNULL:

ГДЕ ЕСТЬNULL(Остатки.Количество, 0) > 0

В условии соединения ЕСТЬNULL применять стоит с осторожностью: функция вокруг поля связи обычно мешает оптимизатору использовать индекс, и соединение превращается в полный перебор. На больших таблицах это кратно замедляет запрос. Правильнее продумать данные так, чтобы связь шла по «сырым» полям, а ЕСТЬNULL применять уже в списке выборки.

Для проверки «поле пустое или равно значению» часто достаточно конструкции Поле ЕСТЬ NULL в сочетании с ИЛИ — это читается проще и не мешает индексации:

ГДЕ Остатки.Количество ЕСТЬ NULL ИЛИ Остатки.Количество = 0

Совместимость типов аргументов

Частая ошибка — подставить значение, тип которого не совпадает с типом поля. Например, ЕСТЬNULL(Документ.Сумма, "0") передаёт строку вместо числа. Запрос может выполниться, но сортировка, итоги и арифметика по такому полю дадут сюрпризы, а в СКД поле получит составной тип.

Если поле имеет составной тип (например, строка неограниченной длины или несколько ссылочных типов), подбирайте замену, которая укладывается в один из допустимых типов. Для ссылок удобен вариант с пустой ссылкой конкретного вида — она корректно отображается и сравнивается.

Для приведения типа замены иногда используют ВЫРАЗИТЬ совместно с ЕСТЬNULL, но в большинстве случаев достаточно литерала правильного типа: 0 для чисел, "" для строк, ДАТАВРЕМЯ(1,1,1) для дат, ИСТИНА/ЛОЖЬ для булевых.

Типичные ошибки
01
Подстановка строки вместо числа — ломаются итоги и сортировка
02
ЕСТЬNULL в условии соединения — потеря индекса и резкое замедление
03
Ожидание, что NULL = 0: сравнение без ЕСТЬNULL теряет строки
04
Забытая обработка NULL в вычисляемых полях — NULL + число даёт NULL
05
Замена NULL на текст-заглушку в поле, по которому потом считают суммы

ЕСТЬNULL в СКД и динамических списках

В схеме компоновки данных NULL-значения особенно заметны: ресурс с NULL не участвует в агрегатах корректно, а группировки показывают пустые ячейки. Рекомендация простая — обрабатывайте ЕСТЬNULL все поля-ресурсы и числовые измерения ещё в тексте запроса набора данных, а не вычисляемыми полями.

В динамических списках произвольного запроса та же логика: если список строится с левыми соединениями, оберните показатели в ЕСТЬNULL, иначе пользователи увидят пустые колонки там, где ожидают нули. Это также упрощает отборы, которые пользователь настраивает через интерфейс.

Альтернативы и вложенные вызовы

Когда вариантов замены несколько, ЕСТЬNULL вкладывают друг в друга: сначала проверяется первое поле, потом запасное, потом константа. Так реализуют логику «взять цену из последней партии, иначе из карточки, иначе ноль»:

ЕСТЬNULL(Партии.Цена, ЕСТЬNULL(Товары.ЗакупочнаяЦена, 0))

Альтернатива для сложной логики — оператор ВЫБОР, который читается лучше при трёх и более ветках и позволяет проверять не только NULL, но и произвольные условия:

ВЫБОР

КОГДА Остатки.Количество ЕСТЬ NULL ТОГДА 0

КОГДА Остатки.Количество < 0 ТОГДА 0

ИНАЧЕ Остатки.Количество

КОНЕЦ

Для отборов вместо ЕСТЬNULL иногда уместнее комбинация ЕСТЬ NULL с ИЛИ — так условие остаётся индексируемым и прозрачным.

Чем заменить NULL

ЕСТЬNULL

Быстрая подстановка одного значения; ограничение — ровно два аргумента

ВЫБОР...КОГДА

Несколько условий и разная логика веток; длиннее запись

ЕСТЬ NULL в отборе

Сохраняет индекс в условиях; не подставляет значение в выборку

Как проверить результат

После добавления ЕСТЬNULL выполните запрос в консоли запросов и сравните две версии: с функцией и без. Строки, где раньше было пусто, должны показать значения по умолчанию, а общее количество строк не должно измениться — ЕСТЬNULL не фильтрует и не добавляет записи.

Проверьте итоги: суммы по числовым полям с заменёнными NULL должны совпадать с контрольными данными учёта. Если итог изменился, вероятно, NULL раньше «съедал» часть строк в группировке или соединении — разберитесь, какое поведение правильное для вашей задачи.

Контрольные точки

Как проверить результат

Количество строк
Норма

Совпадает с запросом без ЕСТЬNULL

Тревожный признак

Строки появились или пропали

Числовые итоги
Норма

Суммы сходятся с учётными данными

Тревожный признак

Итог изменился без причины

Тип поля
Норма

Единый тип в колонке результата

Тревожный признак

Смешанные типы, ошибки в СКД

Скорость запроса
Норма

Время выполнения не выросло

Тревожный признак

Запрос стал заметно медленнее

Итог

Что важно запомнить

ЕСТЬNULL подставляет значение вместо NULL и не меняет состав строк. Обрабатывайте ею поля после левых соединений и незаполненные реквизиты, следите за совместимостью типов и не используйте её в условиях соединения на больших таблицах.

Частые вопросы

Чем ЕСТЬNULL отличается от проверки ЕСТЬ NULL?

ЕСТЬNULL подставляет значение вместо NULL прямо в выражении и используется в списке полей и вычислениях. ЕСТЬ NULL — логическая проверка для условий ГДЕ и ВЫБОР: она отвечает на вопрос «пусто ли поле», но ничего не подставляет.

Почему сравнение NULL = NULL не работает?

NULL означает отсутствие значения, поэтому любое сравнение с ним, включая равенство, не даёт истины. Для проверки на NULL используйте только конструкцию ПОЛЕ ЕСТЬ NULL или оборачивайте обе стороны сравнения в ЕСТЬNULL с одинаковой заменой.

Можно ли передать в ЕСТЬNULL больше двух значений?

Нет, функция принимает ровно два аргумента. Для цепочки вариантов используйте вложенные вызовы: ЕСТЬNULL(Поле1, ЕСТЬNULL(Поле2, ЗначениеПоУмолчанию)).

Влияет ли ЕСТЬNULL на скорость запроса?

В списке выборки влияние минимально. Замедление возникает, когда функция оборачивает поля в условиях соединения или отбора по индексированным полям — тогда СУБД может отказаться от индекса. Проверяйте на реальных объёмах данных.

Что подставлять вместо NULL для даты?

Обычно пустую дату ДАТАВРЕМЯ(1,1,1) — она корректно отображается как пустая и участвует в сравнениях. Подстановка произвольной реальной даты опасна: такие записи попадут в отборы по периоду.

Нужна ли ЕСТЬNULL при внутреннем соединении?

При внутреннем соединении NULL из-за отсутствия пары не возникает, но поля всё равно могут быть NULL, если реквизит не заполнен в самой таблице. Обрабатывайте такие поля по необходимости, независимо от типа соединения.