При разработке отчетов на системе компоновки данных (СКД) программисты часто сталкиваются с проблемой: стандартная функция Среднее() в ресурсах выдает завышенный результат, если в выборке за определенные периоды (например, месяцы) отсутствуют записи. Система просто игнорирует «пустые» месяцы, вместо того чтобы считать их нулевыми. Рассмотрим подробно, почему так происходит и как заставить отчет учитывать каждый месяц выбранного периода.
Для начала проанализируем механизм работы агрегатных функций. В СКД функция Среднее(Поле) рассчитывается по формуле: Сумма значений / Количество записей. Если в феврале у вас не было продаж, и записи об этом в базе данных нет (строка физически отсутствует в таблице), то СКД даже не «узнает» о существовании этого месяца. В итоге сумма делится на 4 месяца вместо 5, и среднее получается неверным.
Важно различать два состояния: когда в поле записан NULL или 0, и когда записи нет вовсе. Если запись есть, но значение в ней NULL, функция Среднее все равно ее проигнорирует. Если же значение 0, то оно будет учтено. Однако чаще всего проблема именно в полном отсутствии записей в результате запроса за конкретный период.
Самый быстрый способ решить проблему «в лоб», когда мы точно знаем границы периода отчета (например, из параметров), — это переопределить расчет ресурса. Вместо стандартного выбора функции Среднее в колонке «Выражение» на закладке «Ресурсы», мы напишем формулу вручную.
Разберем логику: нам нужно взять общую сумму и разделить ее на количество месяцев между началом и концом периода отчета. Рассмотрим пример выражения для ресурса:
Сумма(Количество) / (РазностьДат(&НачалоПериода, &КонецПериода, "МЕСЯЦ") + 1)
Важные нюансы этого метода:
&НачалоПериода и &КонецПериода (или части стандартного периода &Период.ДатаНачала).+1 к разности дат, так как функция РазностьДат при одинаковом месяце вернет 0, а нам нужно учесть текущий месяц как единицу.Дата, иначе функция РазностьДат выдаст ошибку при выполнении.Проанализируем более профессиональный и гибкий подход — использование механизма Дополнения периодов в СКД. Это позволяет системе виртуально «догенерировать» строки для тех периодов, по которым в базе нет движений.
Чтобы реализовать этот метод, выполним следующие шаги:
ПериодМесяц) установим роль «Период».После этих манипуляций СКД добавит в результат запроса строки с пустыми значениями для недостающих месяцев. Теперь в ресурсах можно использовать более простую конструкцию:
Среднее(ЕСТЬNULL(КоличествоСреднее, 0))
Здесь функция ЕСТЬNULL критически важна: она превратит пустые значения в дополненных строках в нули, и агрегатная функция Среднее корректно включит их в знаменатель.
Иногда требуется рассчитать среднее значение не по календарному периоду, а по количеству фактически имеющихся уникальных аналитик. В этом случае на помощь приходит функция ВычислитьВыражение. Она позволяет обращаться к контексту других группировок или ко всей выборке в целом.
Посмотрим на пример выражения, которое рассчитывает сумму и делит ее на количество различных месяцев, присутствующих в итоговой таблице:
Сумма(Количество) / ВычислитьВыражение("Количество(Различные ПериодМесяц)", , "ОбщийИтог")
Это выражение будет работать корректно в итогах, обеспечивая деление общей суммы на количество уникальных месяцев, которые «прошли» через фильтры отчета.
Выясним, какой метод лучше подходит под разные ситуации:
ВычислитьВыражение.При использовании вычислений в ресурсах всегда проверяйте настройки параметров. Если пользователь изменит период на экране, а ваши формулы в ресурсах завязаны на скрытые параметры, результат может стать непредсказуемым. Всегда старайтесь связывать ДатаНачала и ДатаОкончания в выражениях с теми полями, которые доступны пользователю для редактирования.