Работа с запросами в системе 1С:Предприятие 8 — это базовый навык разработчика, однако задачи агрегации данных часто вызывают вопросы у начинающих специалистов. Одной из типичных ситуаций является необходимость получить «схлопнутую» таблицу с итогами, не используя при этом иерархическую структуру, которую предоставляет предложение ИТОГИ ПО. Разберем детально, как правильно суммировать поля, группировать данные и избегать распространенных ошибок компиляции запроса.
Прежде чем переходить к практике, проанализируем, почему стандартные «Итоги» не всегда подходят для решения задачи. Предложение ИТОГИ ПО в языке запросов 1С предназначено для формирования иерархического результата. Это полезно для отчетов, где нужно видеть детальные записи и «шапки» с суммами над ними. Однако, если наша цель — получить плоскую таблицу, где каждая строка представляет собой уникальную комбинацию измерений с их общими суммами, нам необходимо использовать секцию СГРУППИРОВАТЬ ПО.
Рассмотрим ситуацию: если мы оставим ИТОГИ ПО, система вернет дерево значений. Если же мы применим СГРУППИРОВАТЬ ПО, мы получим компактный результат без лишних уровней вложенности. Это критически важно для дальнейшей обработки данных в коде или выгрузки в таблицу значений.
Основная сложность, с которой сталкиваются разработчики, заключается в синтаксисе секции ВЫБРАТЬ при включенной группировке. Давайте запомним фундаментальное правило: каждое поле, которое мы указываем в списке выбора, должно находиться в одном из двух состояний:
СГРУППИРОВАТЬ ПО (является «измерением» группировки).СУММА, МАКСИМУМ, МИНИМУМ, КОЛИЧЕСТВО или СРЕДНЕЕ).Если мы попытаемся выбрать поле «просто так», не добавив его в группировку и не применив функцию, система выдаст ошибку. Рассмотрим пример корректной структуры запроса:
ВЫБРАТЬ
Продажи.Контрагент КАК Контрагент,
СУММА(Продажи.СуммаОборота) КАК ОбщаяСумма,
МАКСИМУМ(Продажи.Период) КАК ПоследняяПродажа
ИЗ
РегистрНакопления.Продажи.Обороты КАК Продажи
СГРУППИРОВАТЬ ПО
Продажи.Контрагент
В данном примере Контрагент является полем, по которому мы «схлопываем» строки, СуммаОборота — суммируется, а для Периода мы используем функцию МАКСИМУМ, чтобы получить дату самого позднего события в рамках этой группы.
Проанализируем типичную ошибку, когда разработчик пытается написать СГРУППИРОВАТЬ ПО СУММА(Поле1). Это логическая ловушка. Мы группируем ПО значениям полей, а не ПО результатам функций. В секции СГРУППИРОВАТЬ ПО должны указываться только имена полей или выражения без агрегатных функций. Функции суммирования живут исключительно в секции ВЫБРАТЬ.
Если вы используете Конструктор запроса, порядок действий должен быть следующим:
Номенклатура, Склад) в правое верхнее окно.Количество, Сумма) перенесите в правое нижнее окно «Суммируемые поля». Конструктор сам подставит функцию СУММА в текст запроса.Это одна из самых коварных проблем. Вы вроде бы настроили СУММА, но в результате видите много строк, и в каждой сумма равна единице или значению одной конкретной проводки. Выясним причину этого поведения. Группировка работает по уникальному набору всех полей, перечисленных в СГРУППИРОВАТЬ ПО.
Если в группировку попало хотя бы одно поле, которое уникально для каждой исходной строки, группировка фактически аннулируется. Такими полями часто становятся:
Ссылка на документ (каждый документ уникален).НомерСтроки (внутри документа строки всегда разные).Период с точностью до секунды.Регистратор.Чтобы получить общую сумму по контрагенту, необходимо удалить все лишние поля из запроса. Как только вы уберете поле Договор или СрокПросрочки, которые делают строку уникальной, система сможет объединить данные и выдать одну итоговую строку.
Иногда нам нужно вывести в запросе какое-то строковое поле или ссылку, по которой мы не хотим группировать, но точно знаем, что в рамках группы это значение либо одинаковое, либо нам достаточно любого одного. В этом случае мы используем «хак» с функцией МАКСИМУМ.
Например, мы группируем продажи по Номенклатуре, но хотим видеть ЕдиницуИзмерения. Если мы добавим ЕдиницуИзмерения в группировку, и у одной номенклатуры вдруг окажутся разные единицы в разных записях, строки разделятся. Если же мы напишем МАКСИМУМ(ЕдиницаИзмерения), запрос останется стабильным и вернет одну строку.
ВЫБРАТЬ
Продажи.Номенклатура КАК Номенклатура,
МАКСИМУМ(Продажи.Номенклатура.ЕдиницаХраненияОстатков) КАК Единица,
СУММА(Продажи.КоличествоОборот) КАК ВсегоКоличество
ИЗ
РегистрНакопления.Продажи.Обороты КАК Продажи
СГРУППИРОВАТЬ ПО
Продажи.Номенклатура
При суммировании данных из разных таблиц (через ЛЕВОЕ СОЕДИНЕНИЕ) часто возникают значения NULL. Помните, что СУММА(NULL) не вызывает ошибку, но математические операции внутри функции могут привести к неожиданным результатам. Рекомендуем использовать функцию ЕСТЬNULL внутри агрегатов, если вы производите расчеты между полями:
ВЫБРАТЬ
СУММА(ЕСТЬNULL(Таблица.Поле1, 0) + ЕСТЬNULL(Таблица.Поле2, 0)) КАК ОбщийИтог
...
Подведем итог нашему анализу. Чтобы успешно просуммировать поля в запросе 1С, нужно четко разделять поля на те, по которым мы группируем, и те, которые мы агрегируем. Убирайте все лишние разрезы (поля), если они дробят результат, и всегда проверяйте секцию СГРУППИРОВАТЬ ПО на наличие ошибочно вставленных функций.