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

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

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

Как получить и использовать итоги из запроса 1С: обход результата, группировочные записи, итоги по группам и общие итоги, типовые ошибки и примеры кода.

Запрос в 1С редко нужен сам по себе — почти всегда требуется обработать его результат: вывести итоги по группам, подсчитать общие суммы, построить отчёт или заполнить табличную часть документа. Именно на этапе работы с итогами начинающие разработчики чаще всего допускают ошибки: получают дубли строк, теряют итоговые записи или, наоборот, выводят лишние.

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

Материал ориентирован на разработчиков и внедренцев, работающих с встроенным языком 1С. Разберём способы получения результата, обход итоговых записей, типовые сценарии и ограничения, о которых стоит знать до написания кода.

Как формируются итоги в тексте запроса

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

ИТОГИ

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

КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Номенклатура)

ПО

Контрагент,

Период МЕСЯЦ

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

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

Три способа получить результат запроса

Метод Выгрузить() у объекта «РезультатЗапроса» принимает параметр — тип обхода. От него зависит структура полученных данных:

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

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

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

bsl
Выборка = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
Пока Выборка.Следующий() Цикл
    Если Выборка.ТипЗаписи() = ТипЗаписиЗапроса.ОбщийИтог Тогда
        ВсегоСумма = Выборка.Сумма;
    ИначеЕсли Выборка.ТипЗаписи() = ТипЗаписиЗапроса.ИтогПоГруппировке Тогда
        // итог по контрагенту
    Иначе
        // детальная строка
    КонецЕсли;
КонецЦикла;

Обход дерева значений с итогами

Когда результат выгружен в дерево значений, итоги доступны через коллекцию Строки каждого узла. Верхний уровень дерева — это группировочные записи (или общий итог, если задано ОБЩИЕ), вложенные строки — либо следующий уровень группировки, либо детальные записи.

Типовой код обхода двух уровней выглядит так: внешний цикл по строкам дерева даёт итоги по первой группировке, внутренний цикл по Строки текущей строки — итоги второго уровня или детальные данные. Количество уровней вложенности должно соответствовать числу группировок в запросе, иначе вы будете обращаться к несуществующим данным.

Порядок работы с итогами
  1. 1
    Добавьте в текст запроса секцию ИТОГИ с агрегатными функциями и полями группировки
  2. 2
    Выполните запрос и выгрузите результат с обходом ПоГруппировкам
  3. 3
    Обойдите строки дерева: уровень 0 — итоги по первой группировке
  4. 4
    Внутри каждой строки обойдите вложенные строки — следующий уровень или детали
  5. 5
    Проверьте итоговые суммы на контрольном примере с известными данными

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

Типовые сценарии использования итогов

Печатная форма с подытогами

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

Заполнение сводной таблицы

Когда нужна только аналитика без деталей — например, продажи по менеджерам за период — детальные записи вообще не нужны. Обходите только верхний уровень дерева и берите агрегированные значения. Это быстрее, чем выгружать плоскую таблицу и сворачивать её методом Свернуть(), особенно на больших выборках.

Проверка условий перед проведением

Итоги удобны для контроля: например, перед проведением реализации запрос считает сумму задолженности контрагента, и если общий итог превышает лимит, документ не проводится. Здесь достаточно группировки ОБЩИЕ и одной записи результата — никаких циклов не требуется.

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

Ошибки и ограничения при работе с итогами

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

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

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

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

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

Прежде чем встраивать запрос в рабочий код, проверьте его в консоли запросов на копии базы. Консоль показывает дерево результата наглядно: видно, на каком уровне находятся итоги, какие значения принимают агрегаты и нет ли NULL.

Контрольный приём — сравнить общий итог запроса с суммой детальных записей, полученной отдельным простым запросом без группировок. Значения должны совпасть. Если расходятся, причина почти всегда в соединениях таблиц: при соединении «один ко многим» строки дублируются, и итоги завышаются. Лечится группировкой до соединения или использованием РАЗЛИЧНЫЕ там, где это уместно.

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

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

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

Равна сумме детальных записей по тому же полю

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

Итог больше — вероятны дубли из-за соединения таблиц

Значения агрегатных полей
Норма

Числа или 0 после ЕСТЬNULL

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

NULL в расчётных полях

Структура дерева
Норма

Число уровней равно числу группировок плюс общий итог

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

Лишние уровни или пустые группировочные строки

Итоги по иерархии
Норма

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

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

Общий итог выше фактического из-за двойного учёта

Альтернативы прямому обходу итогов

Не всегда итоги запроса нужно обходить вручную. Если цель — отчёт для пользователя, система компоновки данных (СКД) выполнит группировку и вывод итогов самостоятельно: достаточно правильно настроить ресурсы и группировки в схеме. Ручной обход дерева в коде при этом не требуется вовсе.

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

Маршрут решения

Как выбрать подход

Нужен интерактивный отчёт с группировками и настройками пользователяИспользуйте СКД — итоги и группировки строятся без кода
Нужна печатная форма с подытогами по группамВыборка с обходом ПоГруппировкам и вложенные выборки
Нужна одна контрольная сумма для проверки условияЗапрос с ИТОГИ ПО ОБЩИЕ и чтение единственной записи
Таблица уже выгружена и нужна сводка по паре колонокМетоды Свернуть() и Итог() таблицы значений
Итог

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

Итоги существуют только при обходе ПоГруппировкам — в плоской таблице их нет. Проверяйте тип записи выборки, обрабатывайте NULL через ЕСТЬNULL и следите за дублями при соединениях и иерархических группировках. Для отчётов предпочтительна СКД, ручной обход оставьте для печатных форм и проверок в коде.

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

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

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

Как получить только общий итог без группировок?

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

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

Если во всех строках группы агрегируемое поле пустое, результат агрегата — NULL. Оберните поле в запросе функцией ЕСТЬNULL(Поле, 0) или проверяйте значение в коде перед использованием в арифметике.

Чем группировка ПО ИЕРАРХИЯ отличается от обычной?

Группировка с ИЕРАРХИЯ добавляет итоговые записи по всем родительским группам справочника, а не только по самим элементам. Это полезно для отчётов по папкам номенклатуры, но при неаккуратном обходе суммы задваиваются.

Что быстрее: итоги в запросе или Свернуть() у таблицы значений?

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

Можно ли вывести в итоговой строке неагрегированное поле?

Напрямую нет — в группировочной записи заполнены только поля группировки и агрегаты. Включите поле в список группировок или примените к нему агрегат, например МАКСИМУМ, если значение внутри группы одинаковое.