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