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

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

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

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

Почему стандартная конструкция ИТОГИ не подходит?

Рассмотрим ситуацию, описанную автором темы. В запросе используется предложение ИТОГИ МАКСИМУМ(ОстатокКоличество) ПО Организация. Если мы попытаемся добавить расчет общего итога по всем организациям, система столкнется с ограничением: для поля «Общий итог» она применит ту же функцию МАКСИМУМ ко всей выборке. В результате мы увидим самое большое значение среди всех организаций, а не их сумму.

Проанализируем пример кода автора:


ВЫБРАТЬ
    ТоварыНаСкладахОстатки.Организация КАК Организация,
    ТоварыНаСкладахОстатки.Номенклатура КАК Номенклатура,
    ТоварыНаСкладахОстатки.ВНаличииОстаток КАК ОстатокКоличество
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Остатки(&Дата) КАК ТоварыНаСкладахОстатки
ИТОГИ
    МАКСИМУМ(ОстатокКоличество)
ПО
    Организация

Если в организации №1 максимум по товару равен 10, а в организации №2 — 20, то общий итог при использовании МАКСИМУМ покажет 20. Наша же цель — получить 30 (10 + 20). Чтобы добиться этого, нужно изменить подход к построению запроса или настройки отчета.

Способ №1: Использование временных таблиц (чистый запрос)

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

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

Разберем пример реализации этого метода:


// Шаг 1: Получаем максимумы во временную таблицу
ВЫБРАТЬ
    ТоварыНаСкладахОстатки.Организация КАК Организация,
    МАКСИМУМ(ТоварыНаСкладахОстатки.ВНаличииОстаток) КАК МаксОстаток
ПОМЕСТИТЬ ВтМаксимальныеОстатки
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Остатки(&Дата) КАК ТоварыНаСкладахОстатки
СГРУППИРОВАТЬ ПО
    Организация;

// Шаг 2: Складываем эти максимумы
ВЫБРАТЬ
    МаксимальныеОстатки.Организация,
    МаксимальныеОстатки.МаксОстаток
ИЗ
    ВтМаксимальныеОстатки КАК МаксимальныеОстатки
ИТОГИ
    СУММА(МаксОстаток)
ПО
    ОБЩИЕ

В этом случае в поле ОБЩИЕ мы получим корректную сумму значений МаксОстаток. Однако этот метод неудобен, если в отчете нужны детальные записи по номенклатуре, так как соединение детальных записей с агрегатами во временных таблицах может сильно усложнить запрос.

Способ №2: Реализация в СКД через ресурсы (Рекомендуемый)

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

Важное правило: При работе с СКД крайне не рекомендуется использовать ключевое слово ИТОГИ непосредственно в тексте запроса. Это мешает системе компоновки самостоятельно управлять итогами и может приводить к дублированию данных или ошибкам производительности.

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

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

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

Сумма(ВычислитьВыражениеСГруппировкойМассив("Максимум(ОстатокКоличество)", "Организация"))

Как это работает:

Особенности при использовании соединений (LEFT JOIN)

В сообщении №9 автор приводит пример запроса с левым соединением регистра остатков и регистра резервов. Посмотрим на ситуацию внимательнее. При соединении таблиц в запросе часто возникает проблема «размножения» строк. Если у одной позиции номенклатуры в одной организации есть несколько записей в таблице резервов, то основная строка остатков будет продублирована столько же раз.

Если в таком «раздутом» запросе использовать СУММА, результат будет завышен. Использование МАКСИМУМ на уровне группировки Организация помогает отсечь дубли, но именно поэтому последующий расчет общего итога через ВычислитьВыражениеСГруппировкойМассив становится критически важным — он позволяет «схлопнуть» данные корректно на каждом уровне.

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

Резюме

Мы проанализировали проблему расчета сложных итогов и выяснили:

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

← На главную