Как просуммировать итоги нижестоящих группировок в СКД

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

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

Почему обычное суммирование не работает

Разберем ситуацию на примере. Допустим, у нас есть водитель, у которого в течение дня зафиксировано несколько поездок. Если мы выберем Максимум(Пробег), СКД покажет нам пиковое значение пробега для этого водителя. Однако, когда мы переходим к итогам по Гаражу, обычная функция Сумма(Пробег) сложит все физические строки из результата запроса, которые относятся к этому гаражу. Если по каждому водителю было по 10 записей, итоговая сумма будет в разы больше, чем сумма реальных пробегов водителей. Нам же нужно заставить систему сначала найти максимум по каждому водителю, а потом сложить эти промежуточные итоги.

Метод 1: Использование вложенных агрегатов в ресурсах

Самый эффективный и современный способ решения этой проблемы в СКД — использование функции ВычислитьВыражениеСГруппировкойМассив. Эта функция позволяет собрать результаты расчетов по нижестоящей группировке в массив, который затем можно обработать другой агрегатной функцией.

Проанализируем синтаксис, который необходимо использовать на закладке Ресурсы для поля итогов:

Сумма(ВычислитьВыражениеСГруппировкойМассив("Максимум(Пробег)", "ТСВодитель"))

Разберем этот расчет по шагам:

  1. Внутренняя часть: "Максимум(Пробег)" — это выражение, которое будет вычисляться для каждой уникальной записи в группировке, указанной вторым параметром. Обратите внимание, что выражение обязательно пишется в кавычках.
  2. Второй параметр: "ТСВодитель" — это имя группировки, по которой мы хотим собрать данные. Система «пробежится» по всем водителям внутри текущего гаража и для каждого вычислит его персональный максимум.
  3. Функция массива: ВычислитьВыражениеСГруппировкойМассив вернет нам набор (массив) этих самых максимумов.
  4. Внешний агрегат: Сумма(...) сложит все элементы полученного массива, давая нам правильный итог на уровне Гаража.

Метод 2: Настройка расчета по разным группировкам

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

Для одного и того же поля (например, Пробег) мы добавим две строки:

  1. Для группировки ТСВодитель:

    Выражение: Максимум(Пробег)

    Рассчитывать по...: ТСВодитель

  2. Для вышестоящих группировок (Гараж, Общий итог):

    Выражение: Сумма(ВычислитьВыражениеСГруппировкойМассив("Максимум(Пробег)", "ТСВодитель"))

    Рассчитывать по...: Гараж, Организация, Общий итог

Такой подход гарантирует, что система не запутается в контексте вычислений и на каждом уровне применит нужную математическую модель.

Метод 3: Альтернатива через ВычислитьВыражение

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


Сумма(ВычислитьВыражение("Максимум(Пробег)", "ТСВодитель", , "Первая", "Последняя"))

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

Важные нюансы и типичные ошибки

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

Практический пример реализации

Представим, что мы создаем отчет по выработке сотрудников. У нас есть записи о каждом выполненном задании. Нам нужно вывести общую сумму «лучших результатов» каждого сотрудника за месяц по отделам.

Проанализируем ситуацию: в отделе 5 сотрудников. Каждый выполнял задачи, и у каждого есть свой рекорд (максимальный балл). Обычная сумма баллов по отделу нам не интересна — нам нужна сумма их рекордов.

Настраиваем ресурс РекордныйБалл:

Сумма(ВычислитьВыражениеСГруппировкойМассив("Максимум(Балл)", "Сотрудник"))

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

← На главную