Как убрать пустые значения и лишние группировки в запросе 1С при получении данных из разных регистров

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

При разработке сложных отчетов в 1С часто возникает ситуация, когда данные нужно получить одновременно из нескольких источников — например, из регистра Товары на складах и Товары организаций. Нередко в результате выполнения такого запроса или при выводе его в компоновку данных (СКД) появляются «фантомные» пустые строки или пустые группировки. Проанализируем, почему это происходит, и разберем по шагам, как очистить результат запроса от лишних данных.

Причина появления пустых значений: Декартово произведение и некорректные соединения

Разберем ситуацию, представленную в обсуждении. Основная ошибка кроется в способе соединения таблиц. Если в секции ИЗ просто перечислить две таблицы через запятую без указания условий связи (Cross Join), система попытается сопоставить каждую строку первой таблицы с каждой строкой второй. Рассмотрим пример некорректного фрагмента кода:


ИЗ 
    ВТ_Склад КАК ВТ_Склад, 
    РегистрНакопления.ТоварыОрганизаций.ОстаткиИОбороты(...) КАК ТоварыОрганизацийОстаткиИОбороты

В данном случае, если в одной таблице есть записи, а в другой для выбранного склада их нет, или если они не связаны логически, запрос может вернуть избыточное количество строк с неопределенными значениями (NULL). Выясним причину: в 1С такой подход почти всегда ведет к логическим ошибкам. Для объединения данных из независимых регистров правильнее использовать конструкцию ОБЪЕДИНИТЬ ВСЕ.

Использование конструкции ГРУППИРУЮЩИЕ НАБОРЫ

Автор темы столкнулся с проблемой при использовании ГРУППИРУЮЩИХ НАБОРОВ. Эта мощная конструкция SQL позволяет в одном запросе получить итоги по разным разрезам. Однако у нее есть особенность: когда система формирует данные для одного набора полей, поля, принадлежащие другому набору, автоматически заполняются значением NULL.

Рассмотрим, как это выглядит в коде:


СГРУППИРОВАТЬ ПО ГРУППИРУЮЩИМ НАБОРАМ (
    (ВТ_Склад.Склад, ВТ_Склад.Номенклатура, ...),
    (ТоварыОрганизацийОстаткиИОбороты.СкладПоОрганизации, ...)
)

Проанализируем ситуацию: когда запрос выводит данные по первой группе (складской учет), поля из второй группы (учет организаций) будут пустыми. Если в настройках отчета СКД эти поля выведены в одну строку, вы увидите пустые ячейки. Если же по ним построена иерархическая группировка, появится та самая «пустая» строка в отчете.

Решение 1: Замена соединения на ОБЪЕДИНИТЬ ВСЕ

Вместо того чтобы пытаться соединить две таблицы, которые не имеют жесткой связи по регистратору или строке документа, используем объединение. Это самый надежный способ убрать пустые строки при работе с разными регистрами. Посмотрим на пример структуры правильного запроса:


ВЫБРАТЬ
    Т_Склады.Склад КАК Склад,
    Т_Склады.Номенклатура КАК Номенклатура,
    Т_Склады.Количество КАК КоличествоСклад,
    0 КАК КоличествоОрганизация
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Остатки(...) КАК Т_Склады

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Т_Орг.СкладскаяТерритория,
    Т_Орг.Номенклатура,
    0,
    Т_Орг.Количество
ИЗ
    РегистрНакопления.ТоварыОрганизаций.Остатки(...) КАК Т_Орг

При таком подходе мы исключаем появление NULL, заменяя их на типизированные пустые значения (число 0 или пустая ссылка). В результате группировка в СКД будет работать корректно, не создавая лишних веток.

Решение 2: Фильтрация на уровне параметров виртуальных таблиц

Важно помнить, что условие ГДЕ в запросе применяется к уже выбранному результату. Если мы работаем с виртуальными таблицами (ОстаткиИОбороты), фильтры нужно накладывать внутри параметров самой таблицы. Это не только ускоряет работу, но и отсекает пустые значения на раннем этапе.

Проанализируем пример:


// Неправильно:
ВЫБРАТЬ ... ИЗ Регистр.ОстаткиИОбороты() ГДЕ Склад = &Склад

// Правильно:
ВЫБРАТЬ ... ИЗ Регистр.ОстаткиИОбороты(,,,,, Склад = &Склад)

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

Решение 3: Обработка NULL функцией ЕСТЬNULL

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

Пример использования:


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

Затем в условии запроса можно добавить: ГДЕ Склад <> ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка).

Решение 4: Настройка СКД для скрытия пустых строк

Если сам запрос написан верно, но группировки в отчете все равно показывают «Пусто», воспользуемся инструментами системы компоновки данных:

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

Итоги

Для эффективного удаления пустых значений в запросе мы рекомендуем придерживаться следующего алгоритма:

Следуя этим правилам, вы получите чистый и понятный отчет без пустых строк и лишних итогов.

← На главную