При разработке сложных отчетов на системе компоновки данных (СКД) часто возникает задача: в зависимости от значения параметра (например, выбор организации, типа учета или переключателя «План/Факт») получать данные из разных источников — разных регистров или разных временных таблиц. Рассмотрим, как реализовать это максимально эффективно, избежав лишней нагрузки на сервер базы данных.
Типичная ошибка начинающего разработчика — попытка объединить две временные таблицы через ПОЛНОЕ СОЕДИНЕНИЕ (FULL JOIN) и затем выбирать поля через конструкцию ВЫБОР КОГДА. Рассмотрим, почему это неудачный подход:
ГДЕ, чтобы избежать задвоения строк или появления пустых значений.Проанализируем правильные способы решения этой задачи.
Самый простой и эффективный способ внутри одного запроса — это использование оператора ОБЪЕДИНИТЬ ВСЕ (UNION ALL). Вместо того чтобы соединять таблицы «в ширину», мы соединяем их «в длину», отсекая ненужные данные на уровне условий.
Разберем пример реализации. Допустим, у нас есть две временные таблицы ВТ_Регистр1 и ВТ_Регистр2. Нам нужно выбрать данные из одной из них в зависимости от параметра &Параметр.
ВЫБРАТЬ
ВТ_Регистр1.Номенклатура КАК Номенклатура,
ВТ_Регистр1.Количество КАК Количество
ИЗ
ВТ_Регистр1 КАК ВТ_Регистр1
ГДЕ
&Параметр = 1
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
ВТ_Регистр2.Номенклатура,
ВТ_Регистр2.Количество
ИЗ
ВТ_Регистр2 КАК ВТ_Регистр2
ГДЕ
&Параметр = 2
Важный нюанс: Многие разработчики по привычке пишут условия через ВЫБОР КОГДА &Параметр = 1 ТОГДА ИСТИНА ИНАЧЕ ЛОЖЬ КОНЕЦ. Однако платформа 1С позволяет использовать простое сравнение параметра в секции ГДЕ. Это делает код чище и понятнее. Оптимизатор запросов СУБД в большинстве случаев поймет, что одно из условий всегда ложно, и не будет выполнять «пустую» часть запроса.
Если мы хотим добиться максимальной производительности, лучше всего сделать так, чтобы запрос к ненужному регистру вообще не отправлялся в базу данных. Это можно сделать в модуле объекта отчета в процедуре ПриКомпоновкеРезультата.
Посмотрим, как программно отключить неиспользуемый набор данных:
ПриКомпоновкеРезультата проанализируем значение параметра.Использование для того набора данных, который не нужен.
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь; // Берем управление в свои руки
// Получаем значение параметра из настроек компоновщика
ЗначениеПараметра = КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти("ТипИсточника").Значение;
Если ЗначениеПараметра = 1 Тогда
// Отключаем второй набор данных
СхемаКомпоновкиДанных.НаборыДанных.НаборДанныхРегистр2.Использование = Ложь;
Иначе
// Отключаем первый набор данных
СхемаКомпоновкиДанных.НаборыДанных.НаборДанныхРегистр1.Использование = Ложь;
КонецЕсли;
// Выполняем стандартную компоновку с измененной схемой
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.Настройки, ДанныеРасшифровки);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
КонецПроцедуры
Этот метод гарантирует, что 1С не будет даже пытаться подготовить или выполнить запрос к отключенной таблице.
Иногда источники данных настолько разные, что проще всего программно изменить сам текст запроса перед его выполнением. Мы можем использовать в тексте запроса строковый маркер (например, //ИМЯ_ТАБЛИЦЫ) и заменять его на нужное имя метаданных.
Рассмотрим пример изменения свойства Запрос у набора данных:
ТекстЗапроса = СхемаКомпоновкиДанных.НаборыДанных.НаборДанных1.Запрос;
Если &Параметр = 1 Тогда
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИмяТаблицы", "РегистрНакопления.Продажи");
Иначе
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИмяТаблицы", "РегистрНакопления.Закупки");
КонецЕсли;
СхемаКомпоновкиДанных.НаборыДанных.НаборДанных1.Запрос = ТекстЗапроса;
Важно: При таком подходе нужно следить, чтобы состав полей (псевдонимы) в обоих вариантах запроса совпадал, иначе СКД выдаст ошибку при попытке обращения к несуществующим полям.
При выборе метода ориентируйтесь на следующие критерии:
ОБЪЕДИНИТЬ ВСЕ с простыми условиями в ГДЕ.Использование.Выяснив причину медленной работы отчетов при использовании полных соединений, мы пришли к выводу, что чистота кода в 1С напрямую коррелирует с производительностью системы. Использование правильных механизмов платформы позволяет создавать быстрые и легко поддерживаемые отчеты.