Как найти максимальный расход за период внутри группировки в отчете СКД

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

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

Постановка задачи и анализ исходных данных

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

Для начала разберем формулу расхода, которую часто используют, если в наборе данных нет готового поля «Расход»:

(КоличествоБазовыхЕдНачальныйОстаток + КоличествоБазовыхЕдПриход) - КоличествоБазовыхЕдКонечныйОстаток

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

Решение 1: Использование функции ВычислитьВыражениеСГруппировкойМассив

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

Алгоритм настройки:

  1. Перейдем на вкладку «Ресурсы» в схеме компоновки данных.
  2. Выберем поле, которое будет отвечать за максимальный расход (например, назовем его МаксимальныйРасход).
  3. В колонке «Выражение» напишем следующую конструкцию:

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

Проанализируем, что здесь происходит:

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

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

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

Разберем по шагам, как это настроить в окне ресурсов:

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

Таким образом, система будет «понимать»: когда мы находимся внутри месяца — нужно просто сложить цифры. Когда мы поднимаемся на уровень выше к номенклатуре — нужно посмотреть на все итоги месяцев и выбрать самый большой.

Разбор типичных ошибок

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

Параметры "Первая", "Первая" ограничивают область расчета только самой первой строкой текущего контекста. Если вы ищете максимум, указывая такие границы, система сравнит первую строку с самой собой и вернет её значение. Для поиска максимума по всей группировке теоретически можно использовать "Первая", "Последняя", но функция ВычислитьВыражениеСГруппировкойМассив гораздо стабильнее, так как она специально спроектирована для работы с итогами вложенных уровней.

Еще одна проблема — NULL значения. Если в каком-то месяце не было движений, формула (Начальный + Приход) - Конечный может вернуть неожиданный результат или NULL. Всегда используйте проверку:

ЕстьNULL(КоличествоБазовыхЕдРасход, 0)

Альтернативный подход: Расчет на уровне запроса

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

Проанализируем структуру такого запроса:

  1. Во временной таблице (например, ВТ_ЕжемесячныйРасход) мы группируем данные по номенклатуре и месяцу, вычисляя сумму расхода.
  2. В основном запросе мы выбираем данные из этой временной таблицы и еще раз группируем их, но уже только по номенклатуре, используя агрегатную функцию МАКСИМУМ к полю расхода.

ВЫБРАТЬ
    Продажи.Номенклатура КАК Номенклатура,
    НАЧАЛОПЕРИОДА(Продажи.Период, МЕСЯЦ) КАК Месяц,
    СУММА(Продажи.Количество) КАК РасходМесяца
ПОМЕСТИТЬ ВТ_РасходПоМесяцам
ИЗ
    РегистрНакопления.Продажи КАК Продажи
ГРУППИРОВАТЬ ПО
    Продажи.Номенклатура,
    НАЧАЛОПЕРИОДА(Продажи.Период, МЕСЯЦ)
;

ВЫБРАТЬ
    ВТ_РасходПоМесяцам.Номенклатура,
    МАКСИМУМ(ВТ_РасходПоМесяцам.РасходМесяца) КАК МаксимальныйЕжемесячныйРасход
ИЗ
    ВТ_РасходПоМесяцам КАК ВТ_РасходПоМесяцам
ГРУППИРОВАТЬ ПО
    ВТ_РасходПоМесяцам.Номенклатура

Этот метод лишает нас гибкости СКД (например, если пользователь захочет сгруппировать данные не по месяцам, а по неделям, запрос придется переписывать), но он работает быстрее на больших объемах данных, так как СУБД выполняет агрегацию эффективнее, чем построчный перебор в памяти СКД.

Заключение

Мы рассмотрели основной способ нахождения максимального расхода в отчете 1С через СКД. Использование функции ВычислитьВыражениеСГруппировкойМассив является наиболее предпочтительным, так как оно сохраняет все преимущества компоновки данных и позволяет корректно работать с иерархией отчета. Помните о правильной настройке ресурсов для разных уровней группировок и всегда проверяйте данные на наличие NULL.

← На главную