Как в СКД обратиться к временной таблице другого набора данных?

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

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

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

---

Способ 1. Использование связи наборов данных через параметры (классический подход)

Если версия вашей платформы ниже 8.3.17, то передать менеджер временных таблиц напрямую не получится. В этом случае мы можем связать два набора данных на уровне самой СКД, используя вкладку «Связи наборов данных» и передачу параметров.

Рассмотрим алгоритм настройки этого механизма по шагам:

  1. В первом наборе данных (например, НаборДанных1) мы получаем список документов или номенклатуры, которые участвуют в цепочке брака. Нам важно, чтобы на выходе этого набора были ссылки на эти объекты (например, поле ДокументСсылка).
  2. Во втором наборе данных (НаборДанных2) мы пишем запрос к табличным частям или регистрам, где нам нужны подробности. В условие ГДЕ этого запроса мы обязательно добавляем параметр:
    
    ГДЕ
        ТабличнаяЧасть.Ссылка В (&ПараметрДокументы)
    
  3. Переходим на вкладку «Связи наборов данных». Создаем новую строку связи:
    • Источник связи: НаборДанных1;
    • Приемник связи: НаборДанных2;
    • Выражение источника: ДокументСсылка;
    • Выражение приемника: ДокументСсылка;
    • Параметр: указываем имя нашего параметра из второго запроса — ПараметрДокументы.

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

---

Способ 2. Программная передача Менеджера временных таблиц (для платформы 8.3.17 и выше)

Начиная с версии платформы 8.3.17, у разработчиков появилась возможность передавать объект МенеджерВременныхТаблиц непосредственно в процессор компоновки данных. Это позволяет сначала подготовить все тяжелые временные таблицы в обычном запросе, а затем использовать их внутри наборов данных СКД.

Выясним, как реализовать этот подход программно. Нам потребуется отключить стандартную обработку формирования отчета и написать свой код в модуле объекта отчета (в процедуре ПриКомпоновкеРезультата).

Посмотрим на пример программной реализации:


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

Теперь в самом запросе схемы компоновки данных мы можем напрямую писать:


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

Важные технические нюансы работы с МВТ в СКД

При использовании этого революционного метода вы обязательно столкнетесь с тем, что Конструктор запроса СКД будет выдавать ошибку: «Таблица не найдена "ВТ_ЗаказыСБраком"» на этапе сохранения схемы в конфигураторе. Компоновщик запросов ничего не знает о таблицах, которые появятся только в момент работы программы. Как решить эту проблему?

---

Способ 3. Возможности современных версий платформы (8.3.25+)

Если ваша информационная база работает на современных релизах платформы (начиная с 8.3.25), работа со сложными временными таблицами стала еще более производительной и лаконичной за счет появления новых операторов языка запросов:

Таким образом, выбор метода зависит от версии вашей платформы 1С:Предприятие. На старых версиях мы вынуждены использовать связи наборов данных по параметрам, мирясь с нагрузкой на СУБД, либо дублировать код получения ВТ в каждом наборе. На современных версиях (8.3.17+) лучшим и наиболее производительным решением является программная передача предопределенного МенеджераВременныхТаблиц в процессор компоновки данных. При необходимости оценить нюансы новых возможностей 8.3.25+ можно использовать разбор практики и проблем применения оператора ДОБАВИТЬ во временных таблицах.

← На главную