При работе с системой компоновки данных (СКД) разработчики часто сталкиваются с архитектурным ограничением: когда мы используем стандартную иерархию, система автоматически подменяет значения полей группировок, чтобы отобразить всю ветку от корня до элемента. Если же задача требует вывести данные в плоском виде, сохранив информацию о «корневом» родителе в отдельной колонке, стандартные настройки часто не справляются. Давайте разберем, как решить эту задачу, не внося изменений в конфигурацию, используя возможности универсальных отчетов, и не перегружая систему сложными запросами.
Этот способ основан на «хитром» поведении СКД при работе с ресурсами (похожие приемы используются, когда нужно реализовать две разных схемы в отчете). В отличие от измерений, значения ресурсов не переопределяются при использовании иерархических группировок. Это позволяет нам передать данные элемента «сквозь» иерархию.
Ссылка. Для дубликата этого поля установите синоним, например, СсылкаДоп.СсылкаДоп. В выражении просто укажите имя поля СсылкаДоп без каких-либо агрегатных функций (например, Сумма или Максимум нам не нужны).Ссылка (без иерархии). В настройках этой группировки перейдите на вкладку Другие настройки (где также можно настроить скрытие пустых столбцов) и для параметра Расположение группировки установите значение Нет.Ссылка, но уже с включенной иерархией.СсылкаДоп.После группировки или для иерархии и установите отбор: Системные поля.Уровень равно 2 (или иное значение, соответствующее глубине вашей задачи). Также рекомендуется установить свойство Выводить отбор в значение Нет.Логика работы этого метода заключается в том, что первая группировка без иерархии «фиксирует» контекст конкретной строки, а ресурс СсылкаДоп позволяет отобразить значение, которое не будет «искажено» движком СКД при формировании иерархического дерева.
Если структура справочника крайне глубокая или динамически меняется, можно делегировать поиск верхнего родителя внутреннему языку 1С. Это работает быстрее, чем множественные обращения через точку в запросах.
Рассмотрим пример реализации функции, которую можно вызывать из вычисляемых полей СКД:
Функция ПолучитьРодителяВерхнегоУровня(Ссылка) Экспорт
Если Ссылка.Пустая() Тогда
Возврат Ссылка;
КонецЕсли;
Родитель = Ссылка.Родитель;
Пока ЗначениеЗаполнено(Родитель.Родитель) Цикл
Родитель = Родитель.Родитель;
КонецЦикла;
Возврат Родитель;
КонецФункции
Чтобы этот метод работал максимально эффективно, рекомендуем:
СКД параметр АдресСоответствия.СКД указать вызов функции общего модуля.ПараметрыСеанса или Временное хранилище, чтобы один раз вычислить всю карту родителей для всей выборки и передать её в функцию. Это избавит вас от проблемы «запроса в цикле».Анализируя задачу «вылизывания» производительности, мы должны помнить о главном правиле: избегайте обращений через точку в запросах. Если вам нужно получить данные из вышестоящих уровней иерархии для 100 000 элементов, лучше заранее подготовить плоскую таблицу в пакетном запросе.
Рассмотрим структуру пакетного запроса:
ВЫБРАТЬ
Спр.Ссылка КАК Элемент,
Спр.Родитель КАК Родитель
ПОМЕСТИТЬ ВТ_Иерархия
ИЗ Справочник.Номенклатура КАК Спр;
ВЫБРАТЬ
ВТ.Элемент,
ВТ.Родитель КАК КорневойРодитель
ИЗ ВТ_Иерархия КАК ВТ
...
Используя транзитивное замыкание (или последовательное левое соединение фиксированной глубины), вы получите плоскую структуру, которую СКД «проглотит» без каких-либо сложностей. Этот метод является наиболее предпочтительным для высоконагруженных отчетов, так как вся тяжелая работа выполняется на стороне SQL, а не на стороне сервера приложений или движка компоновки данных.
Подводя итог, можно сказать: если вы хотите добиться плоского вывода с иерархией в СКД, сначала попробуйте метод с ресурсами (это «чистый» способ внутри СКД). Если же данных очень много и отчет «тормозит», не бойтесь выносить логику определения корня в структуру запроса или во внешний набор данных, подготовленный на этапе ПриКомпоновкеРезультата.