При работе с Системой Компоновки Данных (СКД) разработчики часто сталкиваются с ситуацией, которая на первый взгляд кажется нелогичной. Пользователь в настройках отчета убирает одну из группировок, ожидая, что данные свернутся, а итоговые суммы пересчитаются для более высокого уровня. Однако вместо аккуратных агрегированных строк он видит те же самые детальные записи, которые просто лишились заголовка удаленной группировки. В результате в отчете появляются дубли, а ресурсы не суммируются.
Давайте подробно разберем, почему так происходит и как исправить такое поведение отчета, чтобы он стал гибким и предсказуемым для пользователя.
Представим себе простой отчет по продажам. В исходном варианте данные сгруппированы по полю Договор, а затем по полю Номенклатура. Ресурсом выступает поле СуммаПродаж.
Исходный вид отчета:
Теперь пользователь заходит в настройки и отключает группировку по полю Договор.
Что ожидает пользователь:
Он предполагает, что отчет "схлопнется" по номенклатуре, а суммы продаж просуммируются. То есть он хочет видеть:
Что происходит на самом деле:
Отчет выводит детальные записи, как они были, но без иерархии по договорам:
Визуально это выглядит как задвоение строк, и данные становятся бесполезными для анализа. Выясним, почему СКД ведет себя именно так.
Ключ к разгадке лежит в механизме оптимизации запросов СКД и в настройках вычисляемых полей, особенно ресурсов. СКД — это умная система. Перед тем как выполнить итоговый запрос к базе данных, она анализирует все настройки отчета: выбранные поля, группировки, отборы, сортировки и, что самое важное, выражения для расчета ресурсов.
На основе этого анализа СКД строит оптимальный SQL-запрос, включая в него только те поля, которые действительно необходимы для построения отчета. Если какое-то поле из набора данных не используется ни в одной настройке, СКД может его "выкинуть" из итоговой выборки для ускорения работы.
Проблема, описанная выше, возникает, когда одно из полей неявно "держит" группировку, которую пользователь пытается убрать. Самый частый виновник — выражение для расчета ресурса.
В нашем примере, скорее всего, для одного из ресурсов было задано выражение, которое жестко привязано к группировке Договор. Например, так:
РассчитатьВыражение("Сумма(СуммаПродаж)", "Договор")
Такая конструкция заставляет СКД рассчитывать сумму продаж именно в контексте группировки "Договор". Когда пользователь убирает эту группировку из структуры отчета, СКД все равно видит, что для расчета ресурса ей необходимо поле Договор. Поэтому она оставляет это поле в итоговом наборе данных. В результате запрос к базе данных возвращает строки в разрезе договоров, и "сворачивания" не происходит, так как для СКД записи с "Товаром А" по разным договорам по-прежнему являются уникальными.
Чтобы отчет работал корректно и гибко реагировал на действия пользователя, следуйте нескольким рекомендациям.
Это первое и самое важное, что нужно сделать. Откройте настройки полей-ресурсов на соответствующей вкладке в схеме компоновки данных.
РассчитатьВыражение("...", "ИмяГруппировки") используйте стандартные агрегатные функции: Сумма(), Количество(), Среднее(), Максимум(), Минимум().Например, вместо РассчитатьВыражение("Сумма(СуммаПродаж)", "Договор") просто напишите в выражении ресурса:
Сумма(СуммаПродаж)
В этом случае СКД будет автоматически применять агрегатную функцию к тому уровню группировки, в котором выводится ресурс. Если это группировка по договору — посчитает сумму по договору. Если пользователь уберет ее и оставит только номенклатуру — посчитает общую сумму по номенклатуре. Это делает отчет по-настоящему гибким.
ВычислитьВыражение для сложных расчетов. Иногда требуется рассчитать показатель в контексте определенной группировки, независимо от текущей структуры отчета (например, посчитать долю продаж по товару от общей суммы по контрагенту). Для таких задач используйте функцию ВычислитьВыражение(). Она выполняет расчет на более высоком уровне иерархии, не "ломая" при этом текущую группировку.Вместо того чтобы выводить сразу детальные записи под одной группировкой, создайте логическую иерархию. В нашем примере правильная структура отчета могла бы выглядеть так:
В этом случае, когда пользователь в настройках отключает видимость группировки "Договор", отчет автоматически сворачивается до уровня "Номенклатура", и все ресурсы корректно суммируются. Такой подход более интуитивен и для пользователя, и для самой СКД.
Если вы не можете найти причину странного поведения отчета, загляните "под капот" СКД. Получите текст запроса, который система компоновки данных генерирует в итоге, и проанализируйте его. Это поможет понять, почему то или иное поле попало в выборку и мешает агрегации.
Как получить текст запроса?
ПриКомпоновкеРезультата) и посмотрите содержимое объекта КомпоновщикМакета.Выполнить(). В его свойствах можно найти сгенерированный текст запроса.SCMP (System Composition).Изучив запрос, вы можете увидеть, что поле Договор осталось в секции ВЫБРАТЬ или в СГРУППИРОВАТЬ ПО, даже когда вы убрали группировку. Это будет прямым указанием на то, что какое-то выражение (скорее всего, в ресурсах) заставляет СКД использовать это поле.
В заключение: проблема "несворачивающихся" записей в СКД почти всегда связана с тем, что разработчик, создавая отчет, не учел возможность его гибкой настройки пользователем. Проверяйте выражения ресурсов на жесткие привязки и стройте логичную иерархию группировок — и ваши отчеты будут работать предсказуемо и корректно в любых вариантах.