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