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