Как в СКД запретить автоматическое наложение отборов на временную таблицу?

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

При разработке отчетов в системе компоновки данных (СКД) разработчики часто сталкиваются с ситуацией, когда запрос состоит из пакета с несколькими временными таблицами. Например, выбираются обороты из двух разных регистров накопления, где измерения имеют одинаковые наименования: Номенклатура, Склад или Организация. Нередко по бизнес-логике требуется, чтобы пользовательский отбор по полю накладывался только на первую таблицу пакета, а вторая таблица оставалась нетронутой и рассчитывала общие или базовые показатели без фильтрации. Однако СКД по умолчанию стремится применить отборы во все части запроса, где обнаружены совпадающие имена полей.

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

Почему СКД применяет отборы ко всем временным таблицам

Платформа использует механизм глубокой оптимизации запросов (push-down предикатов). Если в схеме компоновки включен механизм Автозаполнение, генератор запросов СКД детально анализирует весь пакет. Если пользователь в настройках отчета указывает отбор по определенному измерению, платформа автоматически пытается «протолкнуть» это условие как можно глубже — непосредственно в параметры виртуальных таблиц (в параметр Условие) и в секции ГДЕ всех временных таблиц пакета, где встречаются такие же поля. Кроме того, если во временной таблице поле связывается через ВНУТРЕННЕЕ СОЕДИНЕНИЕ с отфильтрованной таблицей, СКД также стремится продублировать фильтр во избежание считывания лишних строк.

Рассмотрим подробнее способы, позволяющие обойти автоматическое наложение условий и управлять поведением СКД.

Способ 1. Переименование полей во временной таблице или на закладке «Компоновка данных»

Самый простой, быстрый и надежный подход — исключить совпадение имен полей. Если платформа не найдет поле с тем же именем, она не сможет сопоставить его с пользовательским отбором.

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

  1. Во второй временной таблице дадим полям другие псевдонимы (например, вместо Номенклатура укажем НоменклатураБезОтбора).
  2. Если необходимо управлять полями без изменения основного кода выборки, откроем конструктор запроса, перейдем на закладку Компоновка данных и на вкладке Поля переопределим имена полей для компоновки данных.
  3. В итоговом запросе пакета соединяем таблицы по переименованным полям. При этом в результирующей выборке пользователю будет доступно только основное поле Номенклатура из первой таблицы, к которому и привяжется фильтр отчета.

Способ 2. Отключение автозаполнения и ручное описание полей и условий

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

По умолчанию в тексте запроса СКД стоит признак {// ...} и включен флажок Автозаполнение. Если снять этот флаг, СКД перестанет автоматически модифицировать секции запроса, но разработчику потребуется явно описать доступные поля выборки и места применения условий с помощью синтаксиса фигурных скобок:

  1. Снимем флаг Автозаполнение на вкладке «Запрос» в конструкторе схемы компоновки данных.
  2. Для первой таблицы, где отбор должен применяться, вручную укажем блок {ГДЕ ...} или передадим условие внутрь параметров виртуальной таблицы через синтаксис расширения языка запросов СКД:
    
    ВЫБРАТЬ
        Таблица1.Номенклатура КАК Номенклатура,
        Таблица1.КоличествоОборот КАК Количество
    ПОМЕСТИТЬ ВТ_СОтбором
    ИЗ
        РегистрНакопления.Продажи.Обороты(, , , {Номенклатура.* КАК Номенклатура}) КАК Таблица1
    ;
    
  3. Во второй временной таблице фигурные скобки с условиями не указываем. В этом случае генератор СКД оставит запрос второй таблицы неизменным и не будет накладывать пользовательские отборы.

Способ 3. «Скрытие» поля от оптимизатора СКД с помощью выражений

Если изменять структуру полей нежелательно, а отключать автозаполнение слишком трудоемко из-за большого объема запроса, применим прием «разрыва связи» поля с метаданными. Для этого измерение во второй временной таблице оборачивается в простое логическое или системное выражение.

Посмотрим на пример такого кода:


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

При таком подходе имя поля Номенклатура сохраняется, однако оптимизатор СКД больше не может сопоставить выражение напрямую с измерением виртуальной таблицы источника и не внедряет предикат отбора в параметры виртуальной таблицы или в секцию ГДЕ.

Способ 4. Разделение запроса на два набора данных

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

  1. Создадим НаборДанных1, который выбирает данные из первого регистра.
  2. Создадим НаборДанных2 для второго регистра.
  3. Перейдем на вкладку Связи наборов данных и свяжем их по нужному измерению.

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

← На главную