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