Разработка и Конфигурация · 11 мин
Как вывести итоги в запросе 1С
Как вывести итоги в запросе 1С: конструкция ИТОГИ ПО, агрегатная функция СУММА, общие итоги, иерархия и обход результата в коде. Примеры и типичные ошибки.
Итоги в запросе 1С — это агрегированные значения (суммы, количества, средние), рассчитанные по группам записей или по всей выборке целиком. Без них невозможно построить ни один отчёт: обороты по контрагентам, остатки по складам, начисления по сотрудникам — всё это итоги по группировкам.
В языке запросов 1С итоги формируются двумя взаимодополняющими механизмами: агрегатными функциями (СУММА, КОЛИЧЕСТВО, МАКСИМУМ и другими) и секцией ИТОГИ ПО, которая создаёт в результате запроса дополнительные итоговые записи. Понимание разницы между ними определяет, насколько эффективно вы будете обходить результат в коде.
Материал ориентирован на разработчиков и внедренцев, работающих с консолью запросов, конструктором запроса и программным выполнением запросов через объект Запрос. Примеры применимы к управляемым и обычным приложениям на платформе 8.3.
Какие способы вывода итогов существуют в 1С
Первый способ — группировка с агрегатными функциями. Вы указываете поля группировки в секции СГРУППИРОВАТЬ ПО и применяете к остальным полям функции СУММА(), КОЛИЧЕСТВО(), СРЕДНЕЕ(), МАКСИМУМ(), МИНИМУМ(). Результат — плоская таблица, где каждая строка уже является итогом по своей группе.
Второй способ — секция ИТОГИ ПО. Здесь запрос возвращает и детальные записи, и итоговые строки по указанным измерениям, включая возможность получить общий итог по всей выборке. Такой результат обходится в коде через Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам).
Третий способ — система компоновки данных (СКД). В отчётах на СКД итоги рассчитываются автоматически по полям-ресурсам, и разработчику достаточно правильно описать ресурс и группировки в настройках схемы. Ручная секция ИТОГИ ПО в тексте запроса СКД чаще всего не нужна.
Сравнение вариантов
Подходит для плоской таблицы итогов без детальных строк. Простой обход результата, но нет вложенности уровней.
Подходит, когда нужны и детальные записи, и итоги по уровням в одном запросе. Требует обхода по группировкам в коде.
Подходит для отчётов: итоги считаются автоматически по группировкам настроек. Ограничение — меньше контроля над текстом запроса.
Итоги через СГРУППИРОВАТЬ ПО и агрегатные функции
Базовый приём: перечислите в секции ВЫБРАТЬ поля группировки и агрегатные выражения, а в конце запроса добавьте СГРУППИРОВАТЬ ПО со всеми неагрегированными полями. Если поле выбрано, но не обёрнуто в агрегатную функцию и не включено в группировку, запрос вернёт ошибку.
ВЫБРАТЬ
Продажи.Контрагент КАК Контрагент,
СУММА(Продажи.СуммаОборот) КАК СуммаПродаж,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Продажи.Регистратор) КАК ЧислоДокументов
ИЗ
РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ) КАК Продажи
СГРУППИРОВАТЬ ПО
Продажи.Контрагент
Обратите внимание на КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ...) — без ключевого слова РАЗЛИЧНЫЕ функция посчитает все строки, включая дубли значений. Для подсчёта уникальных документов или контрагентов РАЗЛИЧНЫЕ обязательно.
Если агрегируемое поле может содержать NULL (например, после левого соединения), оберните его в ЕСТЬNULL(Поле, 0). Иначе СУММА по группе, где все значения NULL, вернёт NULL, что сломает последующие расчёты и вывод в отчёт.
Секция ИТОГИ ПО: многоуровневые итоги
Секция ИТОГИ ПО добавляется после основного запроса и указывает платформе сформировать итоговые записи по перечисленным полям. При этом детальные записи в результате сохраняются — вы получаете дерево «итог → детали».
ВЫБРАТЬ
Продажи.Контрагент КАК Контрагент,
Продажи.Номенклатура КАК Номенклатура,
СУММА(Продажи.СуммаОборот) КАК Сумма
ИЗ
РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ) КАК Продажи
СГРУППИРОВАТЬ ПО
Продажи.Контрагент,
Продажи.Номенклатура
ИТОГИ
СУММА(Сумма)
ПО
Контрагент
В секции ИТОГИ перечисляются агрегатные выражения, которые будут рассчитаны на уровне группировки. Если её опустить и написать просто ИТОГИ ПО Контрагент, платформа сама применит агрегаты к суммируемым полям, но явное указание надёжнее и читаемее.
Можно указать несколько полей через запятую — ИТОГИ ПО Контрагент, Номенклатура — и получить многоуровневую структуру. Ключевое слово ОБЩИЕ в списке (ИТОГИ ПО ОБЩИЕ, Контрагент) добавляет запись с общим итогом по всей выборке.
Обход результата запроса с итогами в коде
Результат запроса с секцией ИТОГИ ПО нельзя корректно обойти обычным линейным циклом — итоговые записи перемешаются с детальными. Используйте выборку с явным способом обхода:
Результат = Запрос.Выполнить();
ВыборкаПоКонтрагентам = Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
Пока ВыборкаПоКонтрагентам.Следующий() Цикл
// Итоговая запись по контрагенту
Сообщить("Контрагент: " + ВыборкаПоКонтрагентам.Контрагент
+ ", сумма: " + ВыборкаПоКонтрагентам.Сумма);
Детали = ВыборкаПоКонтрагентам.Выбрать();
Пока Детали.Следующий() Цикл
// Детальные записи внутри группы
КонецЦикла;
КонецЦикла;
При многоуровневых итогах укажите имя группировки вторым параметром: Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам, "Номенклатура"). Проверить тип текущей записи можно через свойство ТипЗаписи() выборки — оно возвращает значения вроде ТипЗаписиЗапроса.ИтогПоГруппировке или ТипЗаписиЗапроса.ДетальнаяЗапись, что удобно при смешанном обходе.
Если итоги нужны только для выгрузки в таблицу значений, вызовите Результат.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам) — получите дерево значений с вложенными строками. Для плоской таблицы без итогов используйте обычный Выгрузить().
- 1Сформулируйте, какие итоги нужны: плоская таблица или дерево с деталями
- 2Для плоской таблицы напишите СГРУППИРОВАТЬ ПО с агрегатными функциями
- 3Для дерева добавьте секцию ИТОГИ СУММА(Поле) ПО Измерение
- 4Проверьте запрос в консоли запросов на реальных данных
- 5В коде обойдите результат через Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам)
- 6Сверьте общий итог с контрольным отчётом конфигурации
Итоги в отчётах на СКД
В схеме компоновки данных итоги описываются на закладке «Ресурсы»: вы выбираете поле (например, СуммаОборот) и выражение агрегирования — Сумма(СуммаОборот). После этого СКД сама рассчитает итоги по каждой группировке в настройках отчёта и общий итог.
В тексте запроса СКД секцию ИТОГИ ПО обычно не пишут: компоновщик сам добавляет нужные группировки при формировании. Более того, лишние итоги в запросе увеличивают объём выборки и замедляют отчёт. Достаточно корректной группировки или виртуальной таблицы оборотов.
Если итог по ресурсу нужен не по всем группировкам, в поле «Рассчитывать по» на закладке ресурсов укажите конкретную группировку. А для нестандартных расчётов (например, средневзвешенное) используйте собственное выражение ресурса или вычисляемые поля.
Итоги с иерархией и по периодам
Для итогов по иерархии справочника (например, суммы по группам номенклатуры с учётом подгрупп) используйте конструкцию ИТОГИ ПО Номенклатура ИЕРАРХИЯ. Платформа сформирует итоговые записи для каждого родительского элемента. Учтите: группировка по иерархии заметно увеличивает время выполнения на больших справочниках.
Итоги по периодам удобно строить через виртуальные таблицы регистров с параметром периодичности: РегистрНакопления.Продажи.Обороты(, , Месяц, ) вернёт поле Период, по которому можно группировать и строить ИТОГИ ПО Период. Это быстрее, чем группировать детальные записи по функции НАЧАЛОПЕРИОДА(Дата, Месяц).
Проверка результата и типичные ошибки
После написания запроса сверьте итоги с эталонным источником: стандартным отчётом конфигурации или универсальным отчётом по тому же регистру. Расхождение даже в копейках означает ошибку в соединениях, отборе или агрегировании, а не «округление».
Как проверить результат
Совпадает с оборотом по регистру в стандартном отчёте
Расхождение — ищите дубли соединений или неверный отбор
По одной итоговой записи на каждое значение группировки
Итоги перемешаны с деталями при линейном обходе
0 или отсутствие записи, согласно логике
NULL в числовых итогах ломает дальнейшие вычисления
Перед оптимизацией откройте запрос в консоли запросов и посмотрите план: часто замена ИТОГИ ПО на простую группировку сокращает время выполнения в разы, если детальные записи в коде всё равно не используются.
Частые вопросы
Чем отличается СГРУППИРОВАТЬ ПО от ИТОГИ ПО?
Группировка сворачивает строки до уровня группы — детальные записи исчезают. ИТОГИ ПО сохраняет детальные записи и добавляет к ним итоговые строки по указанным измерениям, формируя дерево для обхода по группировкам.
Как вывести общий итог по всей выборке?
Добавьте ключевое слово ОБЩИЕ в список полей итогов: ИТОГИ СУММА(Сумма) ПО ОБЩИЕ. В выборке появится запись типа «Общий итог», которую можно получить первой при обходе по группировкам.
Почему СУММА возвращает NULL?
Если в группе все значения поля равны NULL (типично после левого соединения без совпадений), агрегат вернёт NULL. Оберните поле в ЕСТЬNULL(Поле, 0) до применения СУММА или обработайте NULL в коде.
Можно ли вывести итоги без программирования?
Да. В отчётах на СКД итоги выводятся автоматически по ресурсам, а в универсальном отчёте и динамических списках группировки и итоги настраиваются пользователем через настройки без изменения кода.
Как посчитать количество уникальных значений в итогах?
Используйте КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Поле) — например, КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Регистратор) для числа документов. Без РАЗЛИЧНЫЕ будут посчитаны все строки, включая повторы.
Почему итоги задваиваются после соединения таблиц?
При соединении «один ко многим» строки левой таблицы дублируются, и СУММА считает их повторно. Решение — сгруппировать правую таблицу до соединения во временной таблице или вложенном запросе, чтобы соединение стало «один к одному».
Что важно запомнить
Плоские итоги делайте через СГРУППИРОВАТЬ ПО с агрегатами, многоуровневые — через ИТОГИ ПО с обходом ПоГруппировкам, в отчётах на СКД полагайтесь на ресурсы. Всегда проверяйте дубли соединений, NULL в суммируемых полях и сверяйте итог со стандартным отчётом.