К статье
Практический материал

Разработка и Конфигурация · 10 мин

Как получить итог из запроса 1С

Разбираем, как получить итог из запроса 1С: оператор ИТОГИ ПО, итоги ОБЩИЕ, группировка в выборке, обход результата и типичные ошибки разработчиков.

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

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

Ниже разобраны основные способы получения итогов: оператор ИТОГИ ПО, общие итоги, группировка без иерархии, обход результата запроса, а также типичные ошибки и способы проверить корректность расчёта. Примеры приведены на встроенном языке 1С и языке запросов.

Как работает конструкция ИТОГИ ПО в запросе

Оператор ИТОГИ добавляется в конец текста запроса после выборки и сортировки. Он указывает платформе рассчитать агрегатные значения по указанным полям и сгруппировать результат по заданным измерениям. Базовый синтаксис выглядит так:

ВЫБРАТЬ

Продажи.Контрагент КАК Контрагент,

Продажи.Номенклатура КАК Номенклатура,

СУММА(Продажи.СуммаОборот) КАК Сумма

ИЗ

РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ) КАК Продажи

ИТОГИ

СУММА(Сумма)

ПО

Контрагент

В секции ИТОГИ перечисляются агрегатные функции: СУММА, КОЛИЧЕСТВО, МАКСИМУМ, МИНИМУМ, СРЕДНЕЕ. После ПО указываются поля группировки — по ним платформа сформирует итоговые записи. В примере выше по каждому контрагенту будет рассчитана сумма продаж по всем его позициям номенклатуры.

Важно понимать: поля, по которым строятся итоги, должны присутствовать в выборке запроса. Если поле указано в ПО, но не выбрано в секции ВЫБРАТЬ, конструктор запроса выдаст ошибку. Также поле итоговой группировки нельзя одновременно агрегировать той же функцией без необходимости — это приведёт к избыточным вычислениям.

Общие итоги и итоги по нескольким полям

Если нужен один итог по всему результату запроса — например, общая сумма продаж за период, — используется ключевое слово ОБЩИЕ:

ИТОГИ

СУММА(Сумма)

ПО

ОБЩИЕ

Можно комбинировать: сначала перечислить поля группировки, а в конце добавить ОБЩИЕ через запятую. Тогда в результате будут и итоги по каждой группе, и сводный итог по всей выборке. Это удобно для отчётов, где под таблицей нужна строка «Итого».

Итоги по нескольким полям образуют иерархию. Например, ИТОГИ СУММА(Сумма) ПО Контрагент, Номенклатура создаст итоги по контрагентам, а внутри каждого контрагента — по номенклатуре. Порядок полей в ПО определяет вложенность группировок, поэтому его нужно продумывать под структуру будущего отчёта.

Как обойти итоги в выборке на встроенном языке

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

ВыборкаКонтрагенты = Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

Пока ВыборкаКонтрагенты.Следующий() Цикл

Сообщить("Контрагент: " + ВыборкаКонтрагенты.Контрагент

+ ", итог: " + ВыборкаКонтрагенты.Сумма);

ВыборкаДетали = ВыборкаКонтрагенты.Выбрать();

Пока ВыборкаДетали.Следующий() Цикл

// детальные записи по номенклатуре

КонецЦикла;

КонецЦикла;

Проверить тип текущей записи можно методом ТипЗаписи(). Значение ТипЗаписиЗапроса.ИтогПоГруппировке означает итоговую строку группы, ТипЗаписиЗапроса.ОбщийИтог — общий итог, ТипЗаписиЗапроса.ДетальнаяЗапись — обычную строку данных. Это полезно при плоском обходе, когда нужно отфильтровать только итоги или только детали.

Если нужен только общий итог без деталей, проще выбрать его напрямую: Выборка = Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам, "ОБЩИЕ"). Такая выборка вернёт единственную запись с итоговыми значениями по всему результату.

Порядок действий
  1. 1
    Напишите запрос с агрегатной функцией и секцией ИТОГИ ПО по нужным полям
  2. 2
    Выполните запрос и получите результат через Запрос.Выполнить()
  3. 3
    Создайте выборку с ОбходРезультатаЗапроса.ПоГруппировкам
  4. 4
    Обойдите итоговые записи, при необходимости открывая вложенные выборки деталей
  5. 5
    Проверьте итоги сверкой с отчётом или ручным расчётом на тестовых данных

Альтернативы: группировка через СГРУППИРОВАТЬ ПО и свёртка таблицы

Не всегда нужны именно итоговые записи. Если требуется только одна строка на группу без детальных данных, достаточно обычной группировки СГРУППИРОВАТЬ ПО. Результат будет плоским, его можно обходить простым циклом, и он обычно легче по объёму, чем результат с итогами и деталями одновременно.

Выбор между ИТОГИ ПО и СГРУППИРОВАТЬ ПО определяется задачей: итоги нужны, когда в одном результате требуются и детали, и подытоги (типичный отчёт с группировками); группировка — когда детали не интересны вовсе.

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

Сравнение вариантов

ИТОГИ ПО

Подходит для отчётов с деталями и подытогами одновременно; требует обхода ПоГруппировкам

СГРУППИРОВАТЬ ПО

Подходит, когда нужны только агрегаты без деталей; результат плоский и простой в обходе

Свернуть() таблицы значений

Подходит для агрегации уже полученных данных в памяти; неэффективен на больших объёмах

Типичные ошибки при работе с итогами

Самая частая ошибка — обход результата с итогами обычным Выбрать() без указания типа обхода и без проверки ТипЗаписи(). Итоговые строки суммируются вместе с детальными, и итоговая сумма удваивается или утраивается. Признак проблемы — расхождение с контрольным отчётом ровно в целое число раз.

Вторая группа ошибок связана с NULL. Если агрегируемое поле содержит NULL, СУММА его игнорирует, но при соединениях таблиц NULL может появиться неожиданно, и итог окажется занижен. Рекомендуется оборачивать поля в ЕСТЬNULL(Поле, 0) там, где значение может отсутствовать.

Третья ошибка — избыточные итоги. Разработчик добавляет ИТОГИ ПО по множеству полей «про запас», что замедляет выполнение запроса и раздувает результат. Итоги стоит строить только по тем измерениям, которые реально выводятся пользователю.

Типичные ошибки
01
Плоский обход результата с итогами — суммы задваиваются из-за попадания итоговых строк в расчёт
02
Игнорирование NULL в агрегируемых полях — итог занижается без видимой причины
03
Итоги по лишним полям — запрос замедляется, результат раздувается
04
Путаница между ИТОГИ ПО и СГРУППИРОВАТЬ ПО — в отчёт попадают не те строки

Как проверить правильность итогов

Базовая проверка — сверка с эталонным отчётом. Если итоги считаются по регистру накопления, сформируйте стандартный отчёт (например, оборотно-сальдовую ведомость или универсальный отчёт) за тот же период и с теми же отборами и сравните итоговые суммы. Расхождение указывает на ошибку в отборах, соединениях или обходе выборки.

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

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

Контрольные точки

Как проверить результат

Итог группы против суммы деталей
Норма

Значения совпадают

Тревожный признак

Итог больше или меньше суммы строк группы

Общий итог против суммы итогов групп
Норма

Сходится до копейки

Тревожный признак

Расхождение — дубли строк или лишние группировки

Сверка со стандартным отчётом
Норма

Суммы совпадают при тех же отборах

Тревожный признак

Расхождение — проверять период, отборы и соединения

Итог

Что важно запомнить

Итоги в запросе 1С задаются конструкцией ИТОГИ ПО с агрегатными функциями, общий итог — через ИТОГИ ОБЩИЕ. Результат обходят выборкой ПоГруппировкам с проверкой ТипЗаписи, а корректность подтверждают сверкой уровней итогов и стандартным отчётом.

Частые вопросы

Как получить только общий итог без детальных записей?

Используйте секцию ИТОГИ ... ПО ОБЩИЕ и выборку Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам, "ОБЩИЕ"). Она вернёт одну запись с итоговыми значениями. Если детали не нужны вовсе, ещё проще применить СГРУППИРОВАТЬ ПО без группировочных полей — запрос вернёт одну строку с агрегатами.

Почему итог по группе не равен сумме детальных строк?

Чаще всего причина в соединении таблиц, которое дублирует строки, либо в обходе результата без учёта типа записи — тогда итоговые строки суммируются повторно. Проверьте запрос в консоли запросов и убедитесь, что в цикле используется обход ПоГруппировкам.

Можно ли получить итоги по иерархии справочника?

Да. Для иерархического поля укажите его в секции ПО с ключевым словом ИЕРАРХИЯ, например: ИТОГИ СУММА(Сумма) ПО Номенклатура ИЕРАРХИЯ. Платформа добавит итоговые записи по родительским группам справочника.

Что быстрее: ИТОГИ ПО или СГРУППИРОВАТЬ ПО?

Если детальные записи не нужны, СГРУППИРОВАТЬ ПО обычно эффективнее: СУБД возвращает меньше данных, а результат проще обходить. ИТОГИ ПО оправдан, когда в одном результате нужны и детали, и подытоги.

Как посчитать количество уникальных значений в итогах?

Используйте конструкцию КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Поле) в секции итогов или в агрегатной выборке. Она подсчитает число различных значений поля внутри каждой группы, что полезно, например, для подсчёта уникальных контрагентов в продажах.