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

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

При разработке отчетов на Система компоновки данных (СКД) разработчики часто сталкиваются с неожиданным поведением: при выводе группировки Детальные записи идентичные строки с повторяющимися значениями автоматически сворачиваются в одну. Например, если в запросе формируется список пар Менеджер — Партнер с числовым значением 1, но в сам отчет выводятся только поля Менеджер и числовой показатель, СКД выведет по каждому менеджеру ровно одну строку со значением 1 вместо нескольких строк.

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

Причины автоматического сворачивания строк в СКД

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

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

Способ 1. Настройка роли поля «Обязательное»

Разберем наиболее эффективное и изящное решение проблемы на уровне схемы компоновки данных. Мы можем явно запретить СКД оптимизировать и исключать ключевое поле из запроса.

Для этого выполним следующие шаги:

  1. Перейдем на вкладку Наборы данных в схеме компоновки данных.
  2. В таблице полей найдем поле, определяющее уникальность записи (в нашем примере это Партнер).
  3. Откроем колонку Роль для данного поля.
  4. В открывшемся окне редактирования роли установим флаг Обязательное.

Флаг Обязательное сообщает компоновщику макета, что поле необходимо всегда включать в секцию ВЫБРАТЬ итогового запроса, даже если оно отсутствует в настройках выбранных полей отчета. В результате поле останется в выборке, строки перестанут схлопываться, но сам партнер в колонках отчета выводиться не будет.

Способ 2. Использование языка расширения СКД в тексте запроса

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

Посмотрим на пример оформления текста запроса:


ВЫБРАТЬ
    ВТ.Менеджер КАК Менеджер,
    ВТ.Партнер КАК Партнер,
    1 КАК Всего
ИЗ
    ВТ КАК ВТ
{ГДЕ
    ВТ.Партнер.*}

Фигурные скобки {ГДЕ ...} задают необязательную секцию условий компоновки. Наличие поля ВТ.Партнер в этом блоке гарантирует его сохранение в выборке запроса.

Способ 3. Отключение автозаполнения набора данных

Рассмотрим кардинальный метод управления запросом — отключение автозаполнения. По умолчанию для набора данных типа «Запрос» включен флаг Автозаполнение, который и запускает механизм автоматического анализа и вырезания неиспользуемых полей.

Если снять флаг Автозаполнение на вкладке Наборы данных, СКД перестанет модифицировать текст запроса. Запрос передастся в СУБД в исходном виде, и все поля из временных таблиц сохранятся.

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

Способ 4. Использование набора данных «Объект»

Проанализируем ситуацию, когда запрос формируется сложным образом в коде программы. В этом случае мы можем сформировать результат запроса программно в обработчике ПриКомпоновкеРезультата, выгрузить его в объект ТаблицаЗначений и передать в СКД через набор данных типа «Объект».

Посмотрим на пример кода в модуле объекта отчета:


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

Так как готовая ТаблицаЗначений не подвергается оптимизации запросной части СКД, все детализирующие строки будут выведены в отчет в полном объеме.

Способ 5. Искусственная уникализация записей в запросе

Если необходимо сохранить вывод именно детальных записей и при этом гарантировать их уникальность для процессора компоновки, в запрос можно добавить искусственное поле-ключ. Например, порядковый номер строки или уникальный идентификатор.

Рассмотрим вариант с использованием функции АВТОНОМЕРЗАПИСИ() или нумерации полей:


ВЫБРАТЬ
    ВТ.Менеджер КАК Менеджер,
    1 КАК Всего,
    УПОРЯДОЧИТЬ ПО ВТ.Партнер
ИЗ
    ВТ КАК ВТ

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

← На главную