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