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

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

При работе с запросами в системе 1С:Предприятие начинающие разработчики часто сталкиваются с ситуацией, когда в результирующей таблице внезапно появляются строки, заполненные значениями NULL. Особенно часто это происходит при использовании виртуальных таблиц (например, ПродажиОбороты или ОстаткиИОбороты) и предложения ИТОГИ. Давайте разберем по шагам, почему это происходит и как правильно очистить результат запроса от пустых значений.

Выясняем причину появления NULL при использовании ИТОГИ

Прежде всего, проанализируем ситуацию. Когда мы добавляем в текст запроса предложение ИТОГИ, платформа 1С перестает возвращать просто «плоский» список записей. Вместо этого формируется сложная древовидная структура данных. Для этой задачи можно использовать обработку для вывода результата запроса в дерево.

Представим, что мы строим отчет по продажам с группировкой по контрагентам и детализацией до регистратора. Для каждой строки-итога по контрагенту система должна вывести значения в колонках. Но так как итоговая строка объединяет в себе данные нескольких документов, в колонке Регистратор не может быть указан какой-то один конкретный документ. Поэтому платформа подставляет туда NULL. Это не ошибка программы, а логика работы иерархических выборок: данные есть только в тех полях, по которым сделана группировка на данном уровне итогов.

Рассмотрим пример проблемного кода:


ВЫБРАТЬ
    ПродажиОбороты.Контрагент КАК Контрагент,
    ПродажиОбороты.Регистратор КАК Регистратор,
    ПродажиОбороты.СуммаОборот КАК Сумма
ИЗ
    РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, Авто, ) КАК ПродажиОбороты
ИТОГИ
    СУММА(Сумма)
ПО
    ОБЩИЕ,
    Контрагент

В данном случае в результате появятся строки «Общие итоги» и итоги по каждому контрагенту, где в поле Регистратор будет стоять NULL. Если ваша цель — получить только детальные записи без иерархии, использование ИТОГИ излишне.

Способ 1. Использование функции ЕСТЬNULL в полях выбора

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

Разберем, как это реализовать на практике:


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

Важный момент: функция ЕСТЬNULL не удаляет сами строки, она лишь подменяет значение внутри конкретной колонки. Для числовых показателей (сумм) рекомендуется использовать замену на 0, а для ссылочных полей — на пустую ссылку ЗНАЧЕНИЕ(...).

Способ 2. Фильтрация через ГДЕ и ИМЕЮЩИЕ

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

  1. Используйте конструкцию ГДЕ Таблица.Поле ЕСТЬ НЕ NULL для отсечения пустых записей еще на этапе сборки таблиц.
  2. Если нужно исключить итоги, которые не содержат числовых данных (например, нулевые обороты), используйте предложение ИМЕЮЩИЕ.

Пример использования ИМЕЮЩИЕ для отсечения пустых итогов:


ВЫБРАТЬ
    ПродажиОбороты.Контрагент,
    СУММА(ПродажиОбороты.СуммаОборот) КАК Сумма
ИЗ
    РегистрНакопления.Продажи.Обороты КАК ПродажиОбороты
СГРУППИРОВАТЬ ПО
    ПродажиОбороты.Контрагент
ИМЕЮЩИЕ
    СУММА(ПродажиОбороты.СуммаОборот) <> 0

Способ 3. Правильный программный обход результата

Зачастую проблема с NULL — это не проблема самого запроса, а проблема способа его обработки в коде. Если вы используете итоги, то при обходе результата через Выбрать() необходимо указывать тип обхода. Рассмотрим подробнее:

Если мы напишем просто Выборка = Результат.Выбрать();, система начнет последовательно перебирать все строки, включая итоговые, где будут NULL. Чтобы этого избежать, нужно использовать обход по группировкам:


ВыборкаКонтрагент = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
Пока ВыборкаКонтрагент.Следующий() Цикл
    // Здесь мы в строке итога по Контрагенту
    ВыборкаДетальные = ВыборкаКонтрагент.Выбрать(); 
    Пока ВыборкаДетальные.Следующий() Цикл
        // А здесь мы работаем только с детальными записями, где нет NULL
    КонецЦикла;
КонецЦикла;

Способ 4. Особенности работы с Системой компоновки данных (СКД)

Если ваш запрос является частью отчета на СКД, то бороться с NULL в самом тексте запроса часто не требуется. Система компоновки данных имеет свои инструменты управления пустотами:

Разница между NULL и Неопределено

Проанализируем терминологию, так как это критично для написания условий. В 1С существуют два разных «пустых» типа:

NULL — это отсутствие данных в базе как таковых. Он появляется при левых соединениях и в итогах. Проверяется только через ЕСТЬ NULL.

Неопределено — это значение переменной или реквизита, который еще не был заполнен (например, в составном типе данных). Проверяется через обычное равенство: ГДЕ Поле = ЗНАЧЕНИЕ(Неопределено).

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

← На главную