При построении отчетов в системе компоновки данных (СКД) часто возникает задача: отобразить справочник с иерархией элементов (где каждый элемент может выступать родителем для других элементов), вывести его собственные числовые показатели (например, сумму продаж) и одновременно рассчитать итоговый показатель по всем подчиненным элементам на всех нижних уровнях вложенности.
При стандартной настройке отчета разработчики сталкиваются с рядом трудностей: задвоение строк при иерархическом выводе, некорректный расчет ресурсов и принудительное отображение всей вышестоящей цепочки предков от самого корня. Разберем по шагам, как правильно настроить ресурсы СКД и структуру отчета для решения этой задачи.
Проанализируем задачу расчета ресурсов. Нам необходимо получить две колонки:
Для собственного показателя на вкладке Ресурсы используется стандартное выражение:
Сумма(СуммаПродаж)
Для вычисления кумулятивного итога по всей ветке иерархии элементов используем функции языка выражений СКД. В поле выражения ресурса укажем расчет по группировке:
ВычислитьВыражение("Сумма(СуммаПродаж)", "Контрагент", "ГруппировкаНеРесурса")
Также для вычисления агрегата по массиву подчиненных записей иерархии можно применить следующую конструкцию:
Сумма(ВычислитьВыражениеСГруппировкойМассив("Сумма(СуммаПродаж)", "Контрагент", "Иерархия"))
Данные выражения заставляют СКД агрегировать показатели по всему дереву подчинения, корректно суммируя собственные данные родительского элемента со всеми его потомками на любой глубине.
Выясним причину дублирования записей. В справочниках с иерархией «Группы и элементы» папки не содержат собственных движений в регистрах. Но в иерархии «Элементы» каждый элемент одновременно выступает и узлом иерархии, и носителем собственных данных. Из-за этого СКД по умолчанию может выводить строку узла-родителя, а под ней — ту же самую строку в качестве детальной записи.
Чтобы исключить появление лишних дублирующих строк, рассмотрим следующие варианты настройки:
Контрагент вместо стандартного типа «Иерархия» укажем тип «Только иерархия». В этом случае компоновщик не создает дублирующую детальную строку под узлом, а объединяет вывод в одну строку.Разберем ситуацию, когда пользователь устанавливает отбор по конкретному родителю (например, показать структуру только под выбранным контрагентом). По умолчанию СКД достраивает всю цепочку предков от самого корня справочника, выводя вышестоящие элементы с нулевыми значениями.
Для того чтобы отчет начинался строго с выбранного узла и не отображал пустые родительские уровни, применим один из следующих подходов:
На вкладке Связи наборов данных настраиваем рекурсивную связь набора с самим собой:
— Источник связи: НаборДанных1
— Приемник связи: НаборДанных1
— Выражение источник: Родитель (или реквизит связи)
— Выражение приемник: Ссылка
— Иерархия: флаг включен
— Начальное значение связи: параметр отбора &ВыбранныйКонтрагент
При таком подходе СКД строит дерево сверху вниз строго от указанного элемента, не обращаясь к вышестоящим узлам.
Если используется стандартная группировка по иерархии, в свойствах элемента отбора группировки необходимо переключить режим применения условия на «После группировки или для иерархии». Это позволит отсечь строки предков, не удовлетворяющие условиям отбора.
Проанализируем работу решения на больших объемах данных (десятки и сотни тысяч элементов). Рекурсивная выборка СКД и оператор запроса В ИЕРАРХИИ могут приводить к высокой нагрузке на СУБД.
Для высоконагруженных систем целесообразно использовать паттерн Closure Table (таблица связей):
ИерархияКонтрагентов) с измерениями РодительУзла и ПодчиненныйУзел.ИерархияКонтрагентов.РодительУзла = &ВыбранныйКонтрагент. Это позволяет получить все данные по подчиненным элементам одним простым и быстрым запросом без использования тяжелых иерархических конструкций платформы.