Как в СКД рассчитать среднее, которое станет нулем, если в данных есть хотя бы один ноль?

Программист 1С v8.3 (Управляемые формы)
← На главную

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

Анализ проблемы и типичные ошибки

Давайте проанализируем исходную задачу и первоначальную попытку ее решения. Автор пытался написать в выражении ресурса следующую конструкцию:


ЕСЛИ Представление(Оценка) = 0 ТОГДА Среднее(Оценка) = 0 ИНАЧЕ Среднее(Оценка) КОНЕЦ ЕСЛИ

Эта попытка содержит сразу несколько фундаментальных ошибок, понимание которых — ключ к правильному использованию выражений в СКД.

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

Поняв эти ошибки, мы можем перейти к правильным и эффективным способам решения задачи.

Решение 1: Элегантный способ через функцию МИНИМУМ()

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

В настройках отчета СКД перейдите на вкладку "Ресурсы", найдите нужное поле и для него в колонке "Выражение" напишите следующий код:


ВЫБОР
    КОГДА МИНИМУМ(Оценка) = 0
    ТОГДА 0
    ИНАЧЕ Среднее(Оценка)
КОНЕЦ

Разберем по шагам, как это работает:

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

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

Решение 2: Более "говорящий" вариант с функцией Любой()

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

Выражение для ресурса будет выглядеть так:


ВЫБОР
    КОГДА Любой(Оценка = 0)
    ТОГДА 0
    ИНАЧЕ Среднее(Оценка)
КОНЕЦ

Принцип работы здесь еще более очевиден:

Функция Любой(Оценка = 0) буквально означает: "проверить, есть ли в текущей группировке хотя бы одна (любая) запись, где поле Оценка равно 0". Если есть — функция вернет Истина, и итогом будет 0. Если нет — вернет Ложь, и будет рассчитано среднее.

Для нашей задачи оба решения — с МИНИМУМ() и с Любой() — логически эквивалентны и дадут одинаковый результат. Выбор между ними — часто вопрос стиля кодирования и личных предпочтений.

Что делать, если нужно исключить нули из расчета среднего?

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

Чтобы добиться такого поведения, нужно на уровне набора данных (в запросе или в вычисляемом поле) заменить нули на NULL. Создайте вычисляемое поле, например, ОценкаДляСреднего, со следующим выражением:


ВЫБОР
    КОГДА Оценка = 0
    ТОГДА NULL
    ИНАЧЕ Оценка
КОНЕЦ

После этого на вкладке "Ресурсы" для расчета среднего вам будет достаточно использовать простую агрегатную функцию:


Среднее(ОценкаДляСреднего)

В этом случае при расчете среднего все записи, где оценка была равна нулю, будут полностью проигнорированы.

Подведем итог. Для реализации условных вычислений в ресурсах СКД используйте конструкцию ВЫБОР КОГДА и агрегатные функции (МИНИМУМ, МАКСИМУМ, ЛЮБОЙ), чтобы проанализировать весь набор данных в группировке. Это позволяет создавать гибкие и мощные отчеты, отвечающие сложным бизнес-требованиям.

← На главную