Как правильно рассчитать средний коэффициент и итоги в СКД, чтобы они не суммировались?

Программист 1С v8.3 (Управляемые формы) 1С:ERP Управление предприятием Управленческий учет Промышленность, строительство и АПК
← На главную

При разработке отчетов в Системе Компоновки Данных (СКД) мы часто сталкиваемся с задачей расчета производных показателей: средних цен, коэффициентов расхода материалов, процентов выполнения плана и так далее. Распространенной проблемой, с которой сталкиваются разработчики (как начинающие, так и опытные), является некорректный расчет этих показателей в группировках и общих итогах.

Рассмотрим ситуацию, описанную в теме: в детальных записях (строках номенклатуры) коэффициент рассчитывается верно, но в строке "Итого" мы видим бессмысленное огромное число — сумму всех коэффициентов, тогда как нам нужно среднее значение или пересчитанное отношение по всем данным. Разберем подробно, почему так происходит и как настроить отчет правильно.

Суть математической ошибки в итогах

Прежде чем переходить к настройкам в 1С, давайте поймем логику ошибки. Допустим, у нас есть данные по выпуску продукции и расходу материалов:

  1. Строка 1: Материалы = 10, Продукция = 2. Коэффициент = 10 / 2 = 5.
  2. Строка 2: Материалы = 20, Продукция = 4. Коэффициент = 20 / 4 = 5.

Если мы рассчитываем коэффициент прямо в запросе SQL, то для СКД это просто числовое поле. Когда СКД считает общий итог, она по умолчанию применяет функцию Сумма.

Неверный итог (как сейчас): 5 + 5 = 10. Это число не имеет физического смысла.

Правильный итог: Нам нужно разделить общую сумму материалов на общую сумму продукции.
(10 + 20) / (2 + 4) = 30 / 6 = 5.

Чтобы добиться правильного результата, нам нужно перенести логику вычисления из текста запроса на уровень настроек ресурсов СКД.

Этап 1: Подготовка запроса

В исходном примере автор темы пытается выполнить деление непосредственно внутри запроса:


ЕСТЬNULL(ВЫРАЗИТЬ(ПоискМатериаловПоОтчету.КоличествоУпаковокМатериалы КАК ЧИСЛО(15, 4)), 0) 
/ (ВЫРАЗИТЬ(ПроизводствоПереработчика.Количество КАК ЧИСЛО(15, 4))) 
КАК СреднийРасходныйКоэфициент

Это главная ошибка. Если поле СреднийРасходныйКоэфициент приходит из запроса готовым числом, СКД не знает, как оно было получено, и просто складывает эти числа в итогах.

Что нужно сделать:
В запросе мы должны выбрать отдельно числитель и знаменатель. Не делите их в запросе! Выбирайте поля как есть (можно использовать ЕСТЬNULL для замены NULL на 0, если соединение таблиц внешнее).

Пример правильной структуры выборки в запросе:


ВЫБРАТЬ
    ...
    ЕСТЬNULL(ПоискМатериаловПоОтчету.КоличествоУпаковокМатериалы, 0) КАК КоличествоМатериалов,
    ЕСТЬNULL(ПроизводствоПереработчика.Количество, 0) КАК КоличествоПродукции,
    ...

Этап 2: Настройка вкладки "Ресурсы"

Переходим на вкладку Ресурсы в конструкторе схемы компоновки данных. Именно здесь происходит магия правильных итогов.

Нам нужно добавить новое поле ресурса. Если у вас нет отдельного поля для коэффициента в наборе данных (потому что мы убрали его из запроса), мы можем создать Вычисляемое поле.

Шаг 2.1. Создание вычисляемого поля (опционально, но рекомендуется для порядка)

  1. Перейдите на вкладку Вычисляемые поля.
  2. Добавьте новое поле. Назовите его, например, СреднийРасходныйКоэффициент.
  3. В колонке "Выражение" оставьте пустоту или напишите 0 (мы переопределим это в ресурсах). Заголовок задайте удобный для пользователя.

Шаг 2.2. Настройка формулы ресурса

Теперь на вкладке Ресурсы добавляем наше поле СреднийРасходныйКоэффициент.

В колонке Выражение мы должны написать формулу, которая говорит системе: "Сначала просуммируй все материалы, потом просуммируй всю продукцию, и только потом дели".

Формула:

Сумма(КоличествоМатериалов) / Сумма(КоличествоПродукции)

Обратите внимание: мы используем агрегатную функцию Сумма() к каждому операнду отдельно.

Этап 3: Обработка деления на ноль

В отличие от запроса, где мы контролируем данные, в итогах может возникнуть ситуация, когда знаменатель равен нулю (например, продукция не выпущена, а материалы списаны, или данные отфильтрованы). Если знаменатель будет равен 0, отчет выдаст ошибку "Деление на 0" при формировании.

Поэтому выражение ресурса необходимо сделать безопасным. Используем конструкцию ВЫБОР языка выражений СКД:


ВЫБОР 
    КОГДА Сумма(КоличествоПродукции) = 0 
        ТОГДА 0 
    ИНАЧЕ Сумма(КоличествоМатериалов) / Сумма(КоличествоПродукции) 
КОНЕЦ

Этап 4: Разные формулы для разных уровней (Колонка "Рассчитывать по...")

Иногда требуется, чтобы в детальных строках выводилось одно значение (или оно вообще не выводилось), а в итогах — расчетное.

В колонке Рассчитывать по... на вкладке ресурсов можно указать конкретную группировку. Например:

  1. Добавляем поле КоличествоМатериалов. Выражение: Сумма(КоличествоМатериалов). Рассчитывать по: (пусто, для всех).
  2. Добавляем поле СреднийРасходныйКоэффициент. Выражение: Сумма(КоличествоМатериалов) / Сумма(КоличествоПродукции). Рассчитывать по: ОбщийИтог, Организация.

Однако в вашем случае формула Сумма(А)/Сумма(Б) универсальна и подходит для всех уровней, если вам нужно видеть коэффициент и в строках.

Диагностика проблем: "Почему ресурс не считает?"

В обсуждении прозвучал очень полезный совет по отладке отчетов, когда кажется, что СКД игнорирует ваши формулы. Если вы меняете формулу в ресурсах, а результат в отчете не меняется (или выводится просто сумма), попробуйте следующее:

  1. Проверка связи: Временно напишите в поле "Выражение" для ресурса явное число, например 123. Сформируйте отчет.
    • Если во всех ячейках этого поля появилось 123 — значит, ресурс подключен верно, ошибка в вашей формуле или данных.
    • Если осталось старое значение — значит, отчет кешируется, не обновлен, или вы правите не ту схему/вариант отчета.
  2. Проверка варианта отчета: Если отчет подключен как внешний или через "Дополнительные отчеты и обработки", после сохранения изменений в конфигураторе/файле необходимо обновить его в пользовательском режиме или перезагрузить файл в справочнике.
  3. Пользовательские настройки: Иногда пользовательские настройки перекрывают настройки схемы. Попробуйте сбросить настройки отчета в режим "Стандартные".

Оптимизация запроса из примера

В исходном сообщении текст запроса был перегружен конструкциями ВЫРАЗИТЬ(... КАК ЧИСЛО(15,4)). Давайте разберем, нужно ли это.

Пользователь использовал:


ЕСТЬNULL(ВЫРАЗИТЬ(ПоискМатериаловПоОтчету.КоличествоУпаковокМатериалы КАК ЧИСЛО(15, 4)), 0)

Это избыточно. Если поле КоличествоУпаковокМатериалы в базе данных имеет тип Число, то ВЫРАЗИТЬ обычно не требуется, если только вы не хотите принудительно отбросить знаки после запятой до агрегации (что редко нужно).

Достаточно использовать:

ЕСТЬNULL(ПоискМатериаловПоОтчету.КоличествоУпаковокМатериалы, 0)

Функция ЕСТЬNULL обязательна, если вы используете левое соединение (LEFT JOIN), чтобы вместо NULL получить 0. Это критично для арифметических операций, так как NULL + 5 = NULL.

Резюме решения

  1. Уберите деление (расчет коэффициента) из текста Запроса. Выводите поля числителя и знаменателя отдельно.
  2. Перейдите на вкладку Ресурсы.
  3. Для поля коэффициента пропишите выражение:
    
    ВЫБОР КОГДА Сумма(Знаменатель) = 0 ТОГДА 0 ИНАЧЕ Сумма(Числитель) / Сумма(Знаменатель) КОНЕЦ
    
  4. Убедитесь, что отчет обновлен и пользовательские настройки не перекрывают схему.

Используя этот подход, вы получите корректный средневзвешенный коэффициент на любом уровне группировки отчета.

← На главную