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