При построении отчетов в системе 1С:Предприятие одной из самых распространенных задач является вычисление процентного соотношения показателей, например, процента исполнения бюджета или доли продаж. Однако начинающие разработчики часто сталкиваются с ситуацией, когда в детальных записях процент отображается верно, а в строках итогов (группировках) появляются странные, огромные числа. В этой статье мы подробно разберем, почему так происходит, и как правильно реализовать расчет процентов в секции ИТОГИ языка запросов.
Рассмотрим стандартную ситуацию: у нас есть поле ОбщееИсполнение и поле СкорректированныйБюджет. В детальных строках запроса мы вычисляем процент следующим образом:
ВЫБОР
КОГДА ВТ_ИмпортФормаКПиКР.СкорректированныйБюджет <> 0
ТОГДА (ВТ_ИмпортФормаКПиКР.ОбщееИсполнение * 100) / ВТ_ИмпортФормаКПиКР.СкорректированныйБюджет
ИНАЧЕ 0
КОНЕЦ КАК ИсполнениеПроцент
Когда мы переходим к секции ИТОГИ, ошибочно хочется написать СУММА(ИсполнениеПроцент). Это главная методологическая ошибка. Платформа 1С в этом случае просто сложит все проценты из детальных записей. Если у вас 10 строк, в каждой из которых исполнение составляет 50%, то в итоге вы получите 500%. Очевидно, что итоговое исполнение по всей группе должно оставаться 50%, если объемы данных в строках сопоставимы.
Выясним причину: итоги по расчетным полям должны вычисляться не как сумма результатов, а по той же формуле, что и детальные записи, но с применением агрегатных функций к операндам.
Для того чтобы получить корректный процент в группировках, нам необходимо указать платформе, что нужно сначала просуммировать числитель, затем просуммировать знаменатель, и только после этого произвести деление. Разберем по шагам, как это выглядит в коде запроса.
Вместо простого суммирования поля ИсполнениеПроцент, в блоке ИТОГИ мы должны прописать формулу:
ИТОГИ
СУММА(ОбщееИсполнение),
СУММА(СкорректированныйБюджет),
ВЫБОР
КОГДА СУММА(СкорректированныйБюджет) <> 0
ТОГДА СУММА(ОбщееИсполнение) / СУММА(СкорректированныйБюджет) * 100
ИНАЧЕ 0
КОНЕЦ КАК ИсполнениеПроцент
ПО
Бюджет,
НомерРаздела
Проанализируем этот фрагмент кода. Обратите внимание, что внутри функции ВЫБОР мы используем СУММА(...) для каждого поля. Это заставляет систему выполнять расчет на уровне итогов для каждой группировки (Бюджет, Номер раздела и т.д.), используя уже накопленные итоги по суммам исполнения и бюджета.
Рассмотрим ситуацию, с которой столкнулся автор темы при попытке исправить код. При написании формулы в итогах без использования агрегатных функций возникает ошибка: "Поле итогов должно либо присутствовать в списке группировок итогов, либо находиться в агрегатной функции итога".
Это происходит, если вы пытаетесь написать так:
(ОбщееИсполнение * 100) / СкорректированныйБюджет КАК ИсполнениеПроцент
Важно помнить: в секции ИТОГИ вне группировок могут находиться только те поля, к которым применены функции СУММА, СРЕДНЕЕ, МИНИМУМ, МАКСИМУМ или КОЛИЧЕСТВО. Даже если вы строите сложную формулу, каждый ее "кирпичик" (поле) должен быть обернут в одну из этих функций.
При работе с реальными данными всегда существует риск возникновения NULL или нулевых значений в знаменателе. Посмотрим на пример безопасного расчета, который учитывает эти нюансы:
КОГДА СУММА(Поле) <> 0.ЕСТЬNULL(Поле, 0) в основной части запроса, чтобы агрегатные функции в итогах работали корректно.ВЫРАЗИТЬ.Пример продвинутого расчета в итогах:
ИТОГИ
СУММА(ОбщееИсполнение),
СУММА(СкорректированныйБюджет),
ВЫРАЗИТЬ(
ВЫБОР
КОГДА СУММА(СкорректированныйБюджет) <> 0
ТОГДА СУММА(ОбщееИсполнение) / СУММА(СкорректированныйБюджет) * 100
ИНАЧЕ 0
КОНЕЦ
КАК ЧИСЛО(15, 2)) КАК ИсполнениеПроцент
ПО
ОБЩИЕ,
Бюджет
Хотя в теме обсуждался чистый язык запросов в консоли, стоит упомянуть, как эта же задача решается в СКД, так как большинство современных отчетов строятся именно на ней. В СКД механизм итогов заменен механизмом Ресурсов.
Чтобы рассчитать процент в СКД правильно:
Сумма(ОбщееИсполнение) / Сумма(СкорректированныйБюджет) * 100.ВЫБОР КОГДА.Главное преимущество СКД в том, что она корректно вычисляет это выражение для любого уровня группировки, включая "Общий итог", без необходимости вручную прописывать уровни в запросе.
Мы проанализировали ситуацию и выяснили, что процент — это относительный показатель, который нельзя просто суммировать. Для получения корректных данных в отчетах 1С необходимо соблюдать правило: в итогах процент вычисляется как отношение суммы числителей к сумме знаменателей. Использование конструкции ВЫБОР КОГДА СУММА(...) <> 0 гарантирует стабильную работу кода без ошибок деления на ноль, а функция ВЫРАЗИТЬ обеспечит опрятный вид чисел в итоговой таблице.