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

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

Как вывести итоги в запросе 1С

Как вывести итоги в запросе 1С: конструкция ИТОГИ ПО, агрегатная функция СУММА, общие итоги, иерархия и обход результата в коде. Примеры и типичные ошибки.

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

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

Материал ориентирован на разработчиков и внедренцев, работающих с консолью запросов, конструктором запроса и программным выполнением запросов через объект Запрос. Примеры применимы к управляемым и обычным приложениям на платформе 8.3.

Какие способы вывода итогов существуют в 1С

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

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

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

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

СГРУППИРОВАТЬ ПО + агрегаты

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

ИТОГИ ПО

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

Ресурсы СКД

Подходит для отчётов: итоги считаются автоматически по группировкам настроек. Ограничение — меньше контроля над текстом запроса.

Итоги через СГРУППИРОВАТЬ ПО и агрегатные функции

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

ВЫБРАТЬ

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

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

КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Продажи.Регистратор) КАК ЧислоДокументов

ИЗ

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

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

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

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

Если агрегируемое поле может содержать NULL (например, после левого соединения), оберните его в ЕСТЬNULL(Поле, 0). Иначе СУММА по группе, где все значения NULL, вернёт NULL, что сломает последующие расчёты и вывод в отчёт.

Секция ИТОГИ ПО: многоуровневые итоги

Секция ИТОГИ ПО добавляется после основного запроса и указывает платформе сформировать итоговые записи по перечисленным полям. При этом детальные записи в результате сохраняются — вы получаете дерево «итог → детали».

ВЫБРАТЬ

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

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

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

ИЗ

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

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

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

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

ИТОГИ

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

ПО

Контрагент

В секции ИТОГИ перечисляются агрегатные выражения, которые будут рассчитаны на уровне группировки. Если её опустить и написать просто ИТОГИ ПО Контрагент, платформа сама применит агрегаты к суммируемым полям, но явное указание надёжнее и читаемее.

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

Обход результата запроса с итогами в коде

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

Результат = Запрос.Выполнить();

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

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

// Итоговая запись по контрагенту

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

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

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

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

// Детальные записи внутри группы

КонецЦикла;

КонецЦикла;

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

Если итоги нужны только для выгрузки в таблицу значений, вызовите Результат.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам) — получите дерево значений с вложенными строками. Для плоской таблицы без итогов используйте обычный Выгрузить().

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

Итоги в отчётах на СКД

В схеме компоновки данных итоги описываются на закладке «Ресурсы»: вы выбираете поле (например, СуммаОборот) и выражение агрегирования — Сумма(СуммаОборот). После этого СКД сама рассчитает итоги по каждой группировке в настройках отчёта и общий итог.

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

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

Итоги с иерархией и по периодам

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

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

Проверка результата и типичные ошибки

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

Типичные ошибки
01
Сумма задваивается из-за левого соединения с таблицей, где на одну запись приходится несколько строк — проверяйте кратность соединения
02
Поле включено в ВЫБРАТЬ, но не в СГРУППИРОВАТЬ ПО и не в агрегат — запрос падает с ошибкой
03
Обход результата с ИТОГИ ПО обычным циклом — итоговые строки попадают в обработку как детальные и удваивают суммы
04
СУММА по полю с NULL без ЕСТЬNULL — в итоге NULL вместо числа
05
КОЛИЧЕСТВО без РАЗЛИЧНЫЕ при подсчёте документов — завышенные значения
06
ИТОГИ ПО в запросе СКД — лишняя нагрузка, компоновка и так считает итоги по ресурсам
Контрольные точки

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

Сумма общего итога
Норма

Совпадает с оборотом по регистру в стандартном отчёте

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

Расхождение — ищите дубли соединений или неверный отбор

Количество итоговых записей
Норма

По одной итоговой записи на каждое значение группировки

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

Итоги перемешаны с деталями при линейном обходе

Значения в группах без данных
Норма

0 или отсутствие записи, согласно логике

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

NULL в числовых итогах ломает дальнейшие вычисления

Перед оптимизацией откройте запрос в консоли запросов и посмотрите план: часто замена ИТОГИ ПО на простую группировку сокращает время выполнения в разы, если детальные записи в коде всё равно не используются.
ПЗ
Практическое замечание

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

Чем отличается СГРУППИРОВАТЬ ПО от ИТОГИ ПО?

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

Как вывести общий итог по всей выборке?

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

Почему СУММА возвращает NULL?

Если в группе все значения поля равны NULL (типично после левого соединения без совпадений), агрегат вернёт NULL. Оберните поле в ЕСТЬNULL(Поле, 0) до применения СУММА или обработайте NULL в коде.

Можно ли вывести итоги без программирования?

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

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

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

Почему итоги задваиваются после соединения таблиц?

При соединении «один ко многим» строки левой таблицы дублируются, и СУММА считает их повторно. Решение — сгруппировать правую таблицу до соединения во временной таблице или вложенном запросе, чтобы соединение стало «один к одному».

Итог

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

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