При разработке отчетов в системе 1С:Предприятие часто возникает задача нестандартного расчета итогов. Типовое поведение системы подразумевает суммирование показателей по иерархии группировок, однако в управленческом учете (например, в конфигурации Управление торговлей 10.3) может потребоваться вывести в качестве итога по складу не сумму всех товаров, а максимальное значение среди всех позиций номенклатуры, входящих в этот склад.
В этой статье мы разберем по шагам, как реализовать такую логику с помощью языка запросов 1С и механизмов Системы компоновки данных (СКД).
Рассмотрим ситуацию, когда нам необходимо получить данные из регистра накопления ТоварыОрганизаций. Нам нужно сгруппировать данные по складу и номенклатуре, при этом для номенклатуры рассчитать сумму оборотов, а для склада — выбрать максимальное из этих суммовых значений.
Проанализируем пример кода, который позволяет добиться этого результата напрямую в одном запросе. Основная хитрость заключается в разделении полей для суммирования и полей для поиска максимума в секции ИТОГИ.
ВЫБРАТЬ
ТоварыОрганизацийОбороты.АналитикаУчетаНоменклатуры.Склад КАК Склад,
ТоварыОрганизацийОбороты.АналитикаУчетаНоменклатуры.Номенклатура КАК Номенклатура,
СУММА(ТоварыОрганизацийОбороты.КоличествоПриход) КАК КоличествоПриходМакс,
СУММА(ТоварыОрганизацийОбороты.КоличествоРасход) КАК КоличествоРасходМакс,
СУММА(ТоварыОрганизацийОбороты.КоличествоПриход) КАК КоличествоПриход,
СУММА(ТоварыОрганизацийОбороты.КоличествоРасход) КАК КоличествоРасход
ИЗ
РегистрНакопления.ТоварыОрганизаций.Обороты(&НачалоПериода, &КонецПериода, Период, ) КАК ТоварыОрганизацийОбороты
СГРУППИРОВАТЬ ПО
ТоварыОрганизацийОбороты.АналитикаУчетаНоменклатуры.Склад,
ТоварыОрганизацийОбороты.АналитикаУчетаНоменклатуры.Номенклатура
ИТОГИ
МАКСИМУМ(КоличествоПриходМакс),
МАКСИМУМ(КоличествоРасходМакс),
СУММА(КоличествоПриход),
СУММА(КоличествоРасход)
ПО
ОБЩИЕ,
Склад,
Номенклатура
Разберем подробнее, что происходит в этом запросе. Мы выбираем одни и те же данные (показатели прихода и расхода) дважды, назначая им разные псевдонимы (например, КоличествоПриходМакс и КоличествоПриход). В секции ИТОГИ мы указываем системе, что для одного набора полей нужно использовать функцию МАКСИМУМ, а для другого — СУММА. При обходе результата запроса в иерархии группировок 1С автоматически рассчитает максимум на уровне склада среди всех значений, рассчитанных для номенклатуры.
Если структура данных более сложная или требуется предварительная обработка показателей, эффективнее использовать вложенные запросы. Этот метод позволяет четко разделить этап агрегации данных по номенклатуре и этап поиска максимума по складу.
Рассмотрим пример с использованием регистра ПартииТоваровНаСкладах:
ВЫБРАТЬ
ВложенныйЗапрос.Склад КАК Склад,
МАКСИМУМ(ВложенныйЗапрос.КоличествоКонечныйОстаток) КАК МаксОстаток,
СУММА(ВложенныйЗапрос.КоличествоКонечныйОстаток) КАК СуммОстаток
ИЗ
(ВЫБРАТЬ
ПартииТоваровНаСкладахОстаткиИОбороты.Склад КАК Склад,
ПартииТоваровНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура,
СУММА(ПартииТоваровНаСкладахОстаткиИОбороты.КоличествоКонечныйОстаток) КАК КоличествоКонечныйОстаток
ИЗ
РегистрНакопления.ПартииТоваровНаСкладах.ОстаткиИОбороты(&Начало, &Конец, , , ) КАК ПартииТоваровНаСкладахОстаткиИОбороты
СГРУППИРОВАТЬ ПО
ПартииТоваровНаСкладахОстаткиИОбороты.Склад,
ПартииТоваровНаСкладахОстаткиИОбороты.Номенклатура) КАК ВложенныйЗапрос
СГРУППИРОВАТЬ ПО
ВложенныйЗапрос.Склад
В данном случае мы сначала "сворачиваем" все движения до уровня уникальной пары Склад-Номенклатура во внутреннем запросе. Затем внешний запрос анализирует полученную таблицу и выбирает из нее максимальное значение для каждого склада. Это гарантирует, что МАКСИМУМ будет искаться именно среди итоговых остатков по товарам, а не среди отдельных записей регистра.
Хотя запросы являются мощным инструментом, современным стандартом разработки в 1С является СКД. В компоновке данных решение задачи "Максимум по номенклатуре в итоге склада" выглядит более элегантно и не требует дублирования полей в запросе.
Выясним, как настроить расчет ресурсов в СКД для получения нужного результата:
Количество в список ресурсов.Сумма(Количество).Склад.Склад используем функцию: Максимум(ВычислитьВыражениеСГруппировкойМассив("Сумма(Количество)", "Номенклатура")).Проанализируем работу этой функции: ВычислитьВыражениеСГруппировкойМассив сначала создает виртуальный массив, состоящий из сумм по каждой номенклатуре внутри текущего склада, а внешняя функция Максимум выбирает из этого массива наибольшее число. Это наиболее гибкий метод, так как он позволяет пользователю менять структуру отчета в пользовательском режиме без переписывания запроса.
Стоит отметить технический нюанс: в тексте обсуждения упоминается использование поля АналитикаУчетаНоменклатуры.Склад. Данная структура характерна для УТ 11 или ERP. Если вы работаете в классической УТ 10.3 на обычных формах, то склад и номенклатура будут являться прямыми измерениями регистров накопления (например, ТоварыНаСкладах). При написании кода обязательно проверьте имена полей в вашем метаданных, чтобы избежать ошибки "Поле не найдено".
Также помните о производительности. При использовании МАКСИМУМ в итогах по большим таблицам оборотов рекомендуется всегда ограничивать выборку параметрами виртуальных таблиц &НачалоПериода и &КонецПериода, чтобы система не обрабатывала лишние данные прошлых лет.