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

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

Как убрать NULL в запросе 1С

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

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

Основной инструмент — встроенная функция языка запросов ЕСТЬNULL (в английском синтаксисе — ISNULL). Она принимает два аргумента: проверяемое выражение и значение, которое подставляется, если первое равно NULL. Этого достаточно для большинства задач, но есть и альтернативы: конструкция ВЫБОР (CASE), изменение типа соединения и фильтрация с IS NULL.

Ниже разобраны все рабочие способы с примерами кода, ограничения каждого подхода и типичные ошибки, из-за которых NULL «возвращается» даже после обработки.

Откуда берётся NULL в запросах 1С

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

Второй источник — обращение к реквизитам через точку от поля составного типа или от NULL-ссылки. Если поле «Документ.Контрагент» содержит NULL, то и «Документ.Контрагент.Наименование» вернёт NULL. Третий случай — агрегатные функции над пустой выборкой: СУММА по набору без строк даёт NULL, хотя КОЛИЧЕСТВО в той же ситуации вернёт 0.

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

Функция ЕСТЬNULL — основной способ

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

ВЫБРАТЬ

Номенклатура.Ссылка КАК Товар,

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

ИЗ

Справочник.Номенклатура КАК Номенклатура

ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки

ПО Номенклатура.Ссылка = Остатки.Номенклатура

Важное требование: типы обоих аргументов должны быть совместимы. Если первый аргумент — число, подстановка тоже должна быть числом; если ссылка на справочник — подставляйте пустую ссылку того же справочника через ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка). Подстановка строки вместо числа вызовет ошибку исполнения запроса.

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

bsl
ЕСТЬNULL(ЕСТЬNULL(ЦеныПоставщика.Цена, ЦеныПроизводителя.Цена), 0) КАК Цена

Замена NULL на пустую ссылку и строку

Со ссылочными типами подстановка нуля или пустой строки не пройдёт — запрос упадёт с ошибкой несовместимости типов. Для ссылок используйте литерал ЗНАЧЕНИЕ с указанием пустой ссылки конкретного объекта метаданных.

ВЫБРАТЬ

Заказы.Номенклатура КАК Товар,

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

ИЗ

Документ.ЗаказКлиента.Товары КАК Заказы

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

Особый случай — поля составного типа. Если реквизит может хранить и справочник, и документ, то ЕСТЬNULL с одной пустой ссылкой не решит проблему полностью: поле останется составным, а в СКД и Сводных отчётах это может давать неожиданные представления. В таких случаях поле лучше привести к конкретному типу через ВЫРАЗИТЬ до применения ЕСТЬNULL.

Конструкция ВЫБОР как альтернатива

Когда логика замены сложнее одной подстановки, используйте оператор ВЫБОР (аналог CASE). Он позволяет проверять NULL через условие ЕСТЬ NULL и задавать разные значения для разных ситуаций.

ВЫБРАТЬ

ВЫБОР

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

ТОГДА 0

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

ТОГДА 0

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

КОНЕЦ КАК ДоступныйОстаток

ИЗ

РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки

Преимущество ВЫБОР — гибкость: можно обрабатывать не только NULL, но и граничные значения в одном выражении. Недостаток — громоздкость и чуть более тяжёлый план запроса при массовом использовании по сравнению с одиночным ЕСТЬNULL.

Правило выбора простое: если нужна одна подстановка — берите ЕСТЬNULL, если ветвление по нескольким условиям — ВЫБОР. Смешивать обе конструкции в одном поле без необходимости не стоит: это затрудняет чтение и отладку запроса.

Сравнение способов обработки NULL

ЕСТЬNULL

Быстрая замена NULL на одно значение. Ограничение: типы аргументов должны совпадать.

ВЫБОР ... ЕСТЬ NULL

Подходит для сложной логики с несколькими условиями. Минус — многословность.

Полное соединение + фильтр

Когда NULL нужно не заменить, а исключить строки. Не подходит, если строки нужны в выборке.

Фильтрация и поиск строк с NULL

Иногда задача обратная — не убрать NULL из результата, а найти или, наоборот, исключить строки, где поле пустое. Здесь работает только оператор ЕСТЬ NULL / ЕСТЬ НЕ NULL (IS NULL / IS NOT NULL). Сравнение «Поле = NULL» в условии ГДЕ никогда не сработает, потому что NULL не равен даже самому себе.

ВЫБРАТЬ

Номенклатура.Ссылка КАК Товар

ИЗ

Справочник.Номенклатура КАК Номенклатура

ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки

ПО Номенклатура.Ссылка = Остатки.Номенклатура

ГДЕ

Остатки.Номенклатура ЕСТЬ NULL

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

Учтите тонкость: если соединение левое, то фильтр по полю правой таблицы «ЕСТЬ НЕ NULL» фактически превращает его во внутреннее соединение. Если вам нужны только совпавшие строки, честнее и быстрее сразу писать ВНУТРЕННЕЕ СОЕДИНЕНИЕ — оптимизатор СУБД отработает такой запрос предсказуемее.

Типичные ошибки
01
Условие ГДЕ Поле = NULL — всегда ложно, выборка пустая. Используйте Поле ЕСТЬ NULL.
02
ЕСТЬNULL с несовместимыми типами, например ЕСТЬNULL(СсылочноеПоле, 0) — ошибка исполнения запроса.
03
Замена NULL только в полях ВЫБРАТЬ, но не в условиях соединения и итогах — NULL всплывает в группировках и СКД.
04
Применение ЕСТЬNULL к агрегату СУММА после группировки вместо обработки до неё — промежуточные NULL искажают расчёты.

NULL в группировках, итогах и СКД

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

С агрегатными функциями поведение разное. СУММА, МАКСИМУМ, МИНИМУМ и СРЕДНЕЕ игнорируют NULL в отдельных строках, но если все строки группы NULL, результатом будет NULL. КОЛИЧЕСТВО(Поле) не считает NULL-значения, а КОЛИЧЕСТВО(*) считает все строки. Поэтому СРЕДНЕЕ по полю с NULL и СРЕДНЕЕ по ЕСТЬNULL(Поле, 0) дадут разные результаты — выбирайте вариант осознанно, исходя из смысла показателя.

В СКД NULL дополнительно мешает в ресурсах и вычисляемых полях: выражение «Цена * Количество» при любом NULL-множителе даст NULL, и итог по группе может оказаться пустым. Обрабатывайте NULL либо в тексте запроса набора данных, либо в выражении ресурса через ЕСТЬNULL — функция доступна и в языке выражений СКД.

Если отчёт на СКД показывает пустые итоги при заполненных строках, первым делом проверьте ресурсы на участие в них полей из левых соединений без ЕСТЬNULL. Это самая частая причина «пропадающих» сумм.
ПЗ
Практическое замечание

Проверка результата и производительность

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

По производительности ЕСТЬNULL в полях выборки практически бесплатна. Но ЕСТЬNULL в условиях соединения (ПО ЕСТЬNULL(Таблица.Поле, 0) = ДругаяТаблица.Поле) мешает использованию индексов и может резко замедлить запрос на больших таблицах. Если NULL в ключе соединения мешает, лучше пересмотреть структуру данных или соединяться по двум условиям с ИЛИ через ВЫБОР.

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

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

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

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

Совпадает, если вы не меняли фильтры

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

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

Поля, где был NULL
Норма

Подставлено значение по умолчанию нужного типа

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

Пустые ячейки или ошибка типов

Итоги по суммовым полям
Норма

Сходятся с контрольными данными учёта

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

Итоги уменьшились или обнулились

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

Сопоставимо с исходным

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

Резкий рост после ЕСТЬNULL в условии соединения

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

Чем NULL отличается от пустой ссылки и нуля?

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

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

По логике трёхзначной алгебры NULL не равен ничему, включая сам себя, поэтому результат сравнения — не ИСТИНА и не ЛОЖЬ, а неопределённость, которая отсекает строку из выборки. Правильная запись: Поле ЕСТЬ NULL или Поле ЕСТЬ НЕ NULL.

Как убрать NULL в итогах СКД, если запрос уже с ЕСТЬNULL?

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

Можно ли использовать ЕСТЬNULL в параметрах виртуальных таблиц?

Нет, параметры виртуальных таблиц принимают только конкретные значения, выражения там недопустимы. Замену NULL делайте уже в основном запросе после выборки из виртуальной таблицы.

Что вернёт СУММА, если все значения в группе NULL?

СУММА вернёт NULL, а не ноль. Если в отчёте нужен ноль, оберните агрегат: ЕСТЬNULL(СУММА(Поле), 0) — обработка применяется уже к результату группировки, что корректно работает в языке запросов.

Замедляет ли ЕСТЬNULL выполнение запроса?

В полях выборки и условиях ГДЕ влияние незаметно. Замедление возможно, когда ЕСТЬNULL применяется к полям в условии соединения таблиц — это мешает СУБД использовать индексы. В таких случаях пересмотрите условия связи или структуру запроса.

Итог

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

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