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