Разработка и Конфигурация · 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), для строк — пустую строку или осмысленный текст-заглушку.
ВЫБРАТЬ
Товары.Ссылка КАК Товар,
ЕСТЬ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) для дат, ИСТИНА/ЛОЖЬ для булевых.
ЕСТЬ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(Поле1, ЕСТЬNULL(Поле2, ЗначениеПоУмолчанию)).
Влияет ли ЕСТЬNULL на скорость запроса?
В списке выборки влияние минимально. Замедление возникает, когда функция оборачивает поля в условиях соединения или отбора по индексированным полям — тогда СУБД может отказаться от индекса. Проверяйте на реальных объёмах данных.
Что подставлять вместо NULL для даты?
Обычно пустую дату ДАТАВРЕМЯ(1,1,1) — она корректно отображается как пустая и участвует в сравнениях. Подстановка произвольной реальной даты опасна: такие записи попадут в отборы по периоду.
Нужна ли ЕСТЬNULL при внутреннем соединении?
При внутреннем соединении NULL из-за отсутствия пары не возникает, но поля всё равно могут быть NULL, если реквизит не заполнен в самой таблице. Обрабатывайте такие поля по необходимости, независимо от типа соединения.