Почему функция ЕСТЬNULL в запросе 1С не возвращает значение и как это исправить?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке отчетов и выборок в 1С начинающие разработчики часто сталкиваются с ситуацией: в запросе к табличной части или виртуальной таблице регистра используется функция ЕСТЬNULL (или конструкция ВЫБОР КОГДА ... ТОГДА), однако при отсутствии записей в базе запрос возвращает абсолютно пустой результат (0 строк) вместо ожидаемого значения по умолчанию. Разберем подробно, почему так происходит, и рассмотрим правильные подходы к построению таких запросов.

В чем заключается причина проблемы?

Проанализируем механику работы языка запросов платформы 1С. Функции ЕСТЬNULL, ВЫБОР КОГДА, ЕСТЬ NULL применяются СУБД только к тем строкам, которые уже попали в результирующую выборку.

Если запрос строится напрямую к подчиненной таблице (табличной части объекта) или к виртуальной таблице регистра (например, Обороты или Остатки), и по заданному условию в базе нет ни одной физической записи, СУБД формирует выборку из 0 строк. В этом случае выражениям в секции ВЫБРАТЬ просто не к чему примениться — нет строки, для которой платформа могла бы вычислить значение по умолчанию.

Посмотрим на ошибочный пример запроса к табличной части контактной информации:


ВЫБРАТЬ
    ЕСТЬNULL(ТаблицаКонтактов.НомерТелефона, "11") КАК Поле1,
    ТаблицаКонтактов.Ссылка КАК Ссылка
ИЗ
    Справочник.упКонтактныеЛицаПартнеров.КонтактнаяИнформация КАК ТаблицаКонтактов
ГДЕ
    ТаблицаКонтактов.Ссылка = &Ссылка

Если у указанного контактного лица табличная часть КонтактнаяИнформация пуста, таблица не содержит ни одной строки с данным значением поля Ссылка. Соответственно, результатом выполнения запроса будет пустая таблица, а значение "11" выведено не будет.

Аналогичная ситуация возникает и при прямом обращении к виртуальным таблицам регистров:


ВЫБРАТЬ
    КнигаУчета.Организация КАК Организация,
    ЕСТЬNULL(КнигаУчета.Графа5Оборот, "-") КАК Результат
ИЗ
    РегистрНакопления.КнигаУчетаДоходовИРасходов.Обороты(&Начало, &Конец, , Организация = &Организация) КАК КнигаУчета

Если за выбранный период движений по организации не было, виртуальная таблица оборотов вернет 0 строк, и отчет останется пустым.

Решение: использование ЛЕВОГО СОЕДИНЕНИЯ от главной таблицы

Чтобы гарантированно получить строку в результате запроса (даже если у объекта нет записей в табличной части или движений в регистрах), необходимо сделать ведущей (главной) базовую таблицу сущности и соединить ее через ЛЕВОЕ СОЕДИНЕНИЕ с подчиненной таблицей.

Разберем по шагам правильное построение запроса для получения контактной информации:

  1. В секции ИЗ указываем основную таблицу справочника (например, Справочник.упКонтактныеЛицаПартнеров).
  2. Применяем ЛЕВОЕ СОЕДИНЕНИЕ к табличной части КонтактнаяИнформация по полю связи Ссылка.
  3. Условие отбора в блоке ГДЕ накладываем на ссылку основной таблицы справочника, а не подчиненной.
  4. В секции ВЫБРАТЬ используем обработку отсутствующих значений.

Посмотрим на итоговый правильный текст запроса:


ВЫБРАТЬ
    КЛПартнеров.Ссылка КАК Ссылка,
    ВЫБОР
        КОГДА ТаблицаКонтактов.НомерТелефона ЕСТЬ NULL ИЛИ ТаблицаКонтактов.НомерТелефона = ""
            ТОГДА "11"
        ИНАЧЕ ТаблицаКонтактов.НомерТелефона
    КОНЕЦ КАК НомерТелефона
ИЗ
    Справочник.упКонтактныеЛицаПартнеров КАК КЛПартнеров
    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.упКонтактныеЛицаПартнеров.КонтактнаяИнформация КАК ТаблицаКонтактов
        ПО КЛПартнеров.Ссылка = ТаблицаКонтактов.Ссылка
ГДЕ
    КЛПартнеров.Ссылка = &Ссылка

Теперь рассмотрим исправление аналогичной проблемы с виртуальной таблицей регистра накопления. В качестве ведущей таблицы выбираем справочник организаций:


ВЫБРАТЬ
    Организации.Ссылка КАК Организация,
    ЕСТЬNULL(КнигаУчетаОбороты.Графа5Оборот, 0) КАК Результат
ИЗ
    Справочник.Организации КАК Организации
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.КнигаУчетаДоходовИРасходов.Обороты(
        &Начало,
        &Конец,
        ,
        Организация = &Организация
    ) КАК КнигаУчетаОбороты
        ПО Организации.Ссылка = КнигаУчетаОбороты.Организация
ГДЕ
    Организации.Ссылка = &Организация

Важные нюансы и подводные камни при использовании левого соединения

При реализации запросов с левым соединением важно учитывать следующие технические особенности:

  1. Опасность условий в секции ГДЕ для правой таблицы: если наложить отбор на реквизит правой (подчиненной) таблицы в блоке ГДЕ (например, ГДЕ ТаблицаКонтактов.Вид = &ВидКонтакта), левое соединение автоматически превратится во ВНУТРЕННЕЕ СОЕДИНЕНИЕ, так как строки с NULL будут отсечены. Все дополнительные условия на правую таблицу необходимо указывать строго в секции ПО:
    
    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.упКонтактныеЛицаПартнеров.КонтактнаяИнформация КАК ТаблицаКонтактов
        ПО КЛПартнеров.Ссылка = ТаблицаКонтактов.Ссылка
        И ТаблицаКонтактов.Вид = &ВидКонтакта
    
  2. Параметры виртуальных таблиц: условия по измерениям регистров всегда передавайте в параметры самой виртуальной таблицы, а не в блок ГДЕ. Это критично для производительности и корректности формирования NULL в ненайденных строках.
  3. Дублирование строк при множественных записях: если в табличной части объекта содержится несколько строк (например, несколько телефонов), левое соединение вернет столько строк, сколько записей найдено. Если требуется получить ровно одну строку по объекту, используйте группировку СГРУППИРОВАТЬ ПО с агрегатными функциями (например, МАКСИМУМ(ТаблицаКонтактов.НомерТелефона)) либо точный отбор по виду контакта в секции ПО.

Альтернативные варианты решения

В зависимости от архитектуры задачи можно использовать и другие подходы:

  1. Передача списка значений через Временную Таблицу: если нужно гарантированно вывести набор строк по заранее известному списку (например, перечень контрагентов или дат), сформируйте ТаблицуЗначений в коде, передайте ее в запрос через МенеджерВременныхТаблиц и соединяйте левым соединением с данными базы.
  2. Использование функций БСП: для работы с контактной информацией в типовых конфигурациях 1С рекомендуется использовать программные методы общего модуля УправлениеКонтактнойИнформацией или РаботаСКонтактнойИнформациейКлиентСервер, которые самостоятельно обрабатывают отсутствие записей и возвращают корректные пустые структуры.
  3. Настройки СКД: если запрос разрабатывается для Системы компоновки данных, проблему отсутствующих строк можно решить с помощью флага «Выводить пустые группировки» и настройки выражений ресурсов вида ЕСТЬNULL(Сумма(Графа5Оборот), 0).
← На главную