Расчет процентных показателей в Системе компоновки данных (СКД) — одна из самых частых задач при разработке отчетов. Несмотря на кажущуюся простоту формулы, начинающие разработчики часто сталкиваются с тем, что в детальных записях цифры верны, а в итогах по группировкам или в общем итоге получается либо ноль, либо математически бессмысленное значение. Разберем подробно, почему так происходит и как реализовать расчет правильно.
Рассмотрим типичную ситуацию, описанную в теме. Разработчик пытается рассчитать процент продаж в итоговом запросе СКД. В теории это выглядит логично: мы берем Продажи, делим на Остаток и умножаем на 100. Однако при выводе такого поля в ресурсы СКД возникают проблемы.
Основная причина заключается в том, что СКД работает с данными на двух уровнях: уровне детальных записей (строк запроса) и уровне группировок. Если вы рассчитываете процент в запросе, СКД получает уже готовое число для каждой строки. Когда дело доходит до итогов по группировке (например, по «Номенклатуре» или «Складу»), СКД по умолчанию пытается применить к этому числу агрегатную функцию Сумма. В итоге вместо среднего или корректно вычисленного процента вы получаете «сумму процентов», что не имеет физического смысла.
Пример ошибки:
Для того чтобы итоги считались корректно, расчет процента должен происходить не в запросе, а непосредственно в ресурсах на вкладке «Компоновка данных». Проанализируем правильный алгоритм действий.
В запросе мы оставляем только базовые показатели (числитель и знаменатель) как отдельные числовые поля. Например: ПродажиМаркетплэйсыКоличество, ПереданоНаКомиссиюКоличество и НачальныйОстатокМаркетплэйсы.
Переходим на закладку «Ресурсы» и для поля процента прописываем выражение, в котором агрегатные функции применяются к каждому слагаемому отдельно перед делением. Это критически важный момент. Рассмотрим выражение:
Сумма(ПродажиМаркетплэйсыКоличество) / (Сумма(ПереданоНаКомиссиюКоличество) + Сумма(НачальныйОстатокМаркетплэйсы)) * 100
В этом случае СКД сначала просуммирует все продажи по группировке, затем просуммирует все остатки, и только после этого выполнит деление. Такой подход гарантирует правильный результат на любом уровне иерархии — от детальной записи до общего итога.
При расчете процентов крайне важно предусмотреть ситуацию, когда знаменатель равен нулю. В языке выражений СКД (в ресурсах) это реализуется через конструкцию ВЫБОР. Проанализируем структуру выражения с защитой:
ВЫБОР
КОГДА Сумма(ПереданоНаКомиссиюКоличество) + Сумма(НачальныйОстатокМаркетплэйсы) = 0
ТОГДА 0
ИНАЧЕ Сумма(ПродажиМаркетплэйсыКоличество) * 100 / (Сумма(ПереданоНаКомиссиюКоличество) + Сумма(НачальныйОстатокМаркетплэйсы))
КОНЕЦ
Обратите внимание на несколько нюансов:
Сумма() должна находиться внутри условий ВЫБОР. Если вы просто напишете Сумма(Поле1/Поле2), вы снова вернетесь к ошибке суммирования частных.NULL в исходных данных. Если в знаменателе одно из полей может быть NULL, вся сумма превратится в NULL. В запросе используйте ЕСТЬNULL(Поле, 0) для каждого слагаемого.Выясним причину, по которой иногда в отчете вместо дробного процента (например, 0.5) выводится 0. В языке запросов 1С, если вы делите целое число на целое, результат может быть приведен к целому типу путем отсечения дробной части.
Чтобы этого избежать, мы можем использовать один из следующих приемов:
Число с плавающей точкой.ВЫРАЗИТЬ(Поле КАК ЧИСЛО(15, 2)).Пример в ресурсах СКД:
Выбор
Когда (Сумма(Остаток) * 1.0) = 0 Тогда 0
Иначе (Сумма(Продажи) * 100.0) / (Сумма(Остаток) * 1.0)
Конец
Если вам нужно рассчитать процент, который не зависит от итогов (например, фиксированный коэффициент для каждой строки), можно использовать вкладку «Вычисляемые поля». Однако помните правило: Вычисляемые поля считаются до ресурсов. Если вы создадите вычисляемое поле с формулой процента, а потом добавите его в ресурсы как Сумма(ВашеПоле), итоги будут неверными.
Для корректного отображения вычисляемого поля в итогах, в колонке «Выражение» на вкладке «Ресурсы» все равно нужно продублировать формулу с использованием агрегатных функций Сумма(), как было описано выше.
В СКД есть встроенные функции, которые значительно упрощают жизнь при расчете доли:
ПроцентВГруппе(Значение) — вычисляет процентную долю значения строки относительно общей суммы в текущей группировке.ПроцентВОбщейСумме(Значение) — вычисляет долю относительно самого верхнего итога отчета.Эти функции прописываются в ресурсах. Рассмотрим пример: нам нужно понять, какую долю в общих продажах составляет конкретная номенклатура. В поле «Выражение» ресурса мы напишем:
ПроцентВОбщейСумме(Сумма(ПродажиМаркетплэйсыКоличество))
NULL с помощью ЕСТЬNULL.Сумма() для каждого элемента выражения.ВЫБОР.Сумма для поля, которое уже содержит рассчитанный в запросе процент, если планируете выводить итоги по группировкам.