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