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

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

При разработке отчетов на базе Системы компоновки данных (СКД) часто возникает задача динамического изменения логики получения данных. Типичный сценарий: пользователь выбирает на форме определенный режим (например, "Вариант А" или "Вариант Б"), и в зависимости от этого отчет должен строиться по совершенно разным алгоритмам или источникам данных. В этой статье мы подробно разберем несколько эффективных способов решения этой задачи — от простых манипуляций в языке запросов до продвинутого программного управления схемой компоновки.

Способ 1. Использование логических условий в секции ГДЕ

Если структура выходных полей в обоих запросах совпадает, а меняется только логика отбора или источник (в пределах одной таблицы), мы можем использовать булев параметр для управления условиями выполнения. Рассмотрим ситуацию, когда у нас есть параметр &ЭтоВариантА типа Булево.

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


ВЫБРАТЬ
    Продажи.Номенклатура,
    Продажи.Количество,
    Продажи.Сумма
ИЗ
    РегистрНакопления.Продажи КАК Продажи
ГДЕ
    (&ЭтоВариантА И Продажи.Подразделение = &ПодразделениеА)
    ИЛИ (НЕ &ЭтоВариантА И Продажи.Подразделение = &ПодразделениеБ)

В данном случае СУБД будет отрабатывать только ту часть условия, которая соответствует истинности параметра. Однако стоит помнить, что сложные конструкции с ИЛИ могут негативно сказываться на производительности при работе с очень большими объемами данных, так как оптимизатору запросов сложнее использовать индексы.

Способ 2. Объединение запросов с условием отсечения

Более надежный способ с точки зрения чистоты логики — использование конструкции ОБЪЕДИНИТЬ ВСЕ. Мы можем написать два полных запроса и в каждом из них прописать условие, которое сделает выборку пустой, если параметр не соответствует данному блоку.

Разберем, как это выглядит в тексте запроса СКД:


ВЫБРАТЬ
    Т1.Поле1,
    Т1.Поле2
ИЗ
    РегистрСведений.ДанныеА КАК Т1
ГДЕ
    &Режим = 1

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

ВЫБРАТЬ
    Т2.Поле1,
    Т2.Поле2
ИЗ
    РегистрСведений.ДанныеБ КАК Т2
ГДЕ
    &Режим = 2

В этом примере, если &Режим равен 1, второй запрос вернет пустой результат (так как ГДЕ 1 = 2 всегда ложно), и СКД фактически выведет только данные из первого блока. Платформа 1С достаточно эффективно обрабатывает такие конструкции, часто "отсекая" ненужные ветки запроса еще на этапе планирования исполнения.

Способ 3. Набор данных — объединение в СКД

Вместо того чтобы писать один громоздкий текст запроса с ОБЪЕДИНИТЬ ВСЕ, мы можем использовать встроенные механизмы СКД. Посмотрим, как это настроить в конструкторе схемы:

  1. Создадим два отдельных набора данных типа Набор данных - запрос (например, НаборА и НаборБ).
  2. В каждом запросе пропишем соответствующую логику получения данных.
  3. Создадим третий набор данных — Набор данных - объединение.
  4. Перетащим НаборА и НаборБ внутрь этого объединения.
  5. В каждом вложенном наборе данных (в колонке "Условие отсечения" или просто через параметры ГДЕ) укажем связь с пользовательским параметром.

Этот метод позволяет структурировать схему, делая её более читаемой, особенно если запросы занимают сотни строк кода.

Способ 4. Программная подмена текста запроса

Если логика между вариантами "А" и "Б" настолько разная, что их невозможно (или крайне сложно) объединить в одну структуру, мы можем прибегнуть к программному изменению схемы. Это делается в модуле объекта отчета в процедуре ПриКомпоновкеРезультата.

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


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

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

Способ 5. Использование вариантов отчета

Иногда самым правильным решением с точки зрения архитектуры 1С является создание разных Вариантов отчета в одной СКД. Рассмотрим преимущества этого метода:

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

Резюме и рекомендации

Мы рассмотрели несколько подходов к решению задачи. Выбор конкретного метода зависит от сложности ваших запросов:

  1. Для простых условий используйте ИЛИ в секции ГДЕ.
  2. Для работы с разными таблицами при сохранении структуры полей лучше всего подходит ОБЪЕДИНИТЬ ВСЕ с параметром-флагом.
  3. Для создания профессионального и масштабируемого отчета используйте Варианты отчета или Набор данных - объединение.
  4. К программной подмене текста запроса (НаборДанных.Запрос) стоит прибегать только в самых крайних случаях, когда логика формирования текста должна быть динамической (например, программное построение временных таблиц).

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

← На главную