Как в СКД выводить разные наборы данных или пакеты запросов по условию?

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

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

Почему несвязанные наборы данных не выводятся вместе

Если в схеме компоновки данных создано два набора данных типа «Запрос» и между ними не определены правила на вкладке Связи наборов данных, система компоновки не может автоматически сопоставить строки из одного набора строкам другого. Если добавить поля из обоих несвязанных наборов в одну группировку или таблицу, платформа 1С вернет пустой результат либо выдаст ошибку компоновки.

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

Способ 1. Взаимоисключающие условия в секциях запроса (ОБЪЕДИНИТЬ ВСЕ)

Если результаты двух запросов можно привести к единому набору полей (колонок), оптимальным решением является объединение выборок в рамках одного набора данных «Запрос» с добавлением взаимоисключающего условия по параметру. Разберем, как выглядит текст такого запроса:


ВЫБРАТЬ
    Продажи.Ссылка КАК Документ,
    Продажи.Сумма КАК Сумма
ИЗ
    Документ.РеализацияТоваровУслуг КАК Продажи
ГДЕ
    &ПоПоставщикам = ЛОЖЬ

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

ВЫБРАТЬ
    Закупки.Ссылка КАК Документ,
    Закупки.Сумма КАК Сумма
ИЗ
    Документ.ПоступлениеТоваровУслуг КАК Закупки
ГДЕ
    &ПоПоставщикам = ИСТИНА

Когда параметр &ПоПоставщикам равен ИСТИНА, первая ветка получает заведомо ложное условие ЛОЖЬ = ИСТИНА. Современные СУБД при вычислении ложного константного предиката не сканируют физические таблицы отключенной ветки, за счет чего запрос выполняется быстро и без лишней нагрузки на сервер.

Способ 2. Отсечение выборок в пакете временных таблиц

Если в схеме используется сложный пакет запросов с формированием нескольких временных таблиц, переключение логики можно реализовать через передачу условий в фильтрацию таблиц или конструкцию ВЫБОР в секции ГДЕ:


// В первой временной таблице пакета:
ВЫБРАТЬ
    Таблица1.Ссылка КАК Ссылка
ИЗ
    Справочник.Контрагенты КАК Таблица1
ГДЕ
    &НомерНабора = 1

;

// Во второй временной таблице пакета:
ВЫБРАТЬ
    Таблица2.Ссылка КАК Ссылка
ИЗ
    Справочник.Номенклатура КАК Таблица2
ГДЕ
    &НомерНабора = 2

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

Способ 3. Разделение на независимые варианты отчета

Штатный и наиболее производительный подход в типовых решениях — создание нескольких вариантов отчета внутри одной схемы компоновки данных:

  1. Создаем два независимых набора данных-запроса (например, НаборДанныхПоставщики и НаборДанныхКлиенты).
  2. Переходим на вкладку Настройки и добавляем два варианта отчета.
  3. В первом варианте отчета в структуру группировок и список выбранных полей добавляем исключительно поля из набора НаборДанныхПоставщики.
  4. Во втором варианте отчета настраиваем структуру только с полями из НаборДанныхКлиенты.

Благодаря внутренней оптимизации СКД при выборе пользователем первого варианта отчета запрос второго набора данных даже не будет отправляться в СУБД, что обеспечивает максимальное быстродействие.

Способ 4. Управление видимостью группировок через пользовательские настройки

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

  1. В корне отчета добавляем две независимые группировки: первую — для полей первого набора, вторую — для полей второго.
  2. Для каждой из корневых группировок открываем свойства пользовательских настроек (кнопка с синим значком настройки внизу панели структуры).
  3. Включаем флаг включения в пользовательские настройки и устанавливаем режим редактирования Быстрый доступ.

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

Способ 5. Программное управление в событии ПриКомпоновкеРезультата

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


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    // Получаем текущие настройки компоновщика
    Настройки = КомпоновщикНастроек.ПолучитьНастройки();
    
    // Считываем значение пользовательского параметра
    ПараметрПоПоставщикам = Настройки.ПараметрыДанных.Элементы.Найти("ПоПоставщикам");
    
    Если ПараметрПоПоставщикам <> Неопределено И ПараметрПоПоставщикам.Использование Тогда
        Флаг = ПараметрПоПоставщикам.Значение;
        
        // Управляем активностью корневых группировок отчета
        Если Настройки.Структура.Количество() >= 2 Тогда
            Настройки.Структура[0].Использование = Флаг;
            Настройки.Структура[1].Использование = НЕ Флаг;
        КонецЕсли;
    КонецЕсли;
    
    // Выполняем компоновку с обновленными настройками структуры
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);
    
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
    
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
КонецПроцедуры

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

← На главную