Разработка и Конфигурация · 12 мин
Как просуммировать строки в запросе 1С
Как просуммировать строки в запросе 1С: функция СУММА, СГРУППИРОВАТЬ ПО, ИТОГИ, свёртка таблицы значений и типичные ошибки при суммировании данных.
Суммирование строк — одна из самых частых операций при работе с запросами в 1С. Она нужна, когда требуется получить обороты по контрагенту, остатки по складу, итоговую сумму документов за период или любую другую агрегированную цифру. В языке запросов 1С для этого служит агрегатная функция СУММА(), которая работает в паре с предложением СГРУППИРОВАТЬ ПО.
Главная сложность для начинающих разработчиков — понять, что СУММА не просто складывает числа, а работает в рамках группировки: система сначала разбивает строки на группы по указанным полям, а затем суммирует значения внутри каждой группы. Если группировку не указать, получится одна строка с общим итогом по всей выборке.
Кроме классического варианта с агрегатной функцией, существуют и другие способы получить суммы: итоги по группировкам через ИТОГИ ПО, свёртка таблицы значений в коде, суммирование в схеме компоновки данных. Каждый способ имеет свою область применения и ограничения, которые разберём ниже.
Базовый синтаксис функции СУММА
Минимальный пример суммирования выглядит так: выбираем поле-измерение и сумму числового поля, группируя по измерению. Например, сумма продаж по каждому контрагенту:
ВЫБРАТЬ
Продажи.Контрагент КАК Контрагент,
СУММА(Продажи.Сумма) КАК СуммаПродаж
ИЗ
РегистрНакопления.Продажи КАК Продажи
СГРУППИРОВАТЬ ПО
Продажи.Контрагент
Здесь система сгруппирует все строки регистра по полю «Контрагент» и для каждой группы посчитает сумму поля «Сумма». На выходе — по одной строке на контрагента, независимо от того, сколько записей по нему хранится в регистре.
Если убрать из запроса поле «Контрагент» и группировку, останется только ВЫБРАТЬ СУММА(Продажи.Сумма) — запрос вернёт ровно одну строку с общей суммой по всем записям. Это удобно, когда нужен один итоговый показатель, например общая выручка за период.
Важное правило синтаксиса: все неагрегатные поля в секции ВЫБРАТЬ обязаны присутствовать в предложении СГРУППИРОВАТЬ ПО. Если добавить поле в выборку, но забыть включить его в группировку, конструктор запроса выдаст ошибку ещё на этапе проверки текста.
Суммирование с группировкой по нескольким полям
На практике редко нужен итог по одному измерению. Чаще требуется, например, сумма продаж по контрагенту в разрезе месяцев или по складу в разрезе номенклатуры. Для этого все нужные измерения перечисляются и в выборке, и в группировке:
ВЫБРАТЬ
Продажи.Контрагент КАК Контрагент,
Продажи.Номенклатура КАК Номенклатура,
СУММА(Продажи.Количество) КАК Количество,
СУММА(Продажи.Сумма) КАК Сумма
ИЗ
РегистрНакопления.Продажи КАК Продажи
СГРУППИРОВАТЬ ПО
Продажи.Контрагент,
Продажи.Номенклатура
Каждая комбинация «контрагент + номенклатура» даст отдельную строку результата. Чем больше полей в группировке, тем более детальной будет выборка и тем меньше будет отличаться запрос от простого выбора всех строк. Порядок полей в СГРУППИРОВАТЬ ПО на результат не влияет, но влияет на читаемость запроса.
Если по какой-то группе суммируемое поле во всех строках равно NULL, функция СУММА вернёт NULL, а не ноль. Это частая причина «пустых» цифр в отчётах. Обезопасить себя можно функцией ЕСТЬNULL: СУММА(ЕСТЬNULL(Продажи.Сумма, 0)) — тогда строки с NULL будут учитываться как нулевые.
Фильтрация данных до и после суммирования
Частая задача — просуммировать не все строки, а только подходящие по условию. Здесь есть два разных механизма, и их путаница — типичная ошибка. Предложение ГДЕ отбирает строки до группировки: сначала отсекаются ненужные записи, потом оставшиеся суммируются.
Предложение ИМЕЮЩИЕ работает после группировки и фильтрует уже готовые агрегированные результаты. Например, выбрать контрагентов, у которых сумма продаж превысила порог:
ВЫБРАТЬ
Продажи.Контрагент КАК Контрагент,
СУММА(Продажи.Сумма) КАК СуммаПродаж
ИЗ
РегистрНакопления.Продажи КАК Продажи
ГДЕ
Продажи.Период МЕЖДУ &НачалоПериода И &КонецПериода
СГРУППИРОВАТЬ ПО
Продажи.Контрагент
ИМЕЮЩИЕ
СУММА(Продажи.Сумма) > 100000
Фильтр по периоду вынесен в ГДЕ, потому что он проверяется для каждой исходной строки. Условие на сумму — в ИМЕЮЩИЕ, потому что сумма существует только после группировки. Попытка написать условие на СУММА в секции ГДЕ приведёт к ошибке: на этапе фильтрации строк агрегатных значений ещё не существует.
Как выбрать действие
Суммирование по виртуальным таблицам регистров
Когда данные берутся из регистров накопления или бухгалтерии, вручную суммировать физические записи часто не нужно: платформа предоставляет виртуальные таблицы с уже посчитанными итогами. Для регистра накопления вида «Обороты» это таблица Обороты, для регистра остатков — Остатки и ОстаткиИОбороты.
ВЫБРАТЬ
Обороты.Номенклатура КАК Номенклатура,
Обороты.КоличествоОборот КАК Количество,
Обороты.СуммаОборот КАК Сумма
ИЗ
РегистрНакопления.Продажи.Обороты(&Начало, &Конец, , ) КАК Обороты
Виртуальная таблица оборотов уже возвращает данные, сгруппированные по указанным измерениям, поэтому дополнительная СУММА и группировка не нужны — суммирование выполнено на уровне механизма итогов регистра, что работает заметно быстрее, чем обход всех физических записей.
Период и отборы следует передавать через параметры виртуальной таблицы, а не через ГДЕ. Если отфильтровать результат виртуальной таблицы предложением ГДЕ, платформа сначала построит итоги по всем данным, а потом отбросит лишнее — на больших регистрах это кратно увеличивает время выполнения запроса.
Итоги по группам: ИТОГИ ПО и ОБЩИЕ
Конструкция ИТОГИ ПО решает другую задачу, чем СГРУППИРОВАТЬ ПО: она не схлопывает строки, а добавляет к детальным записям итоговые строки по указанным группам. Результат такого запроса обходится как дерево через ВыборкаПоГруппировкам.
ВЫБРАТЬ
Продажи.Контрагент КАК Контрагент,
Продажи.Номенклатура КАК Номенклатура,
СУММА(Продажи.Сумма) КАК Сумма
ИЗ
РегистрНакопления.Продажи КАК Продажи
СГРУППИРОВАТЬ ПО
Продажи.Контрагент,
Продажи.Номенклатура
ИТОГИ
СУММА(Сумма)
ПО
Контрагент
Добавление ключевого слова ОБЩИЕ в ИТОГИ ПО даст дополнительную строку с общим итогом по всей выборке. Это удобно для отчётов, где нужно показать детализацию, промежуточные суммы и гранд-тотал одним запросом.
Важно понимать разницу: СГРУППИРОВАТЬ ПО уменьшает количество строк до числа групп, а ИТОГИ ПО сохраняет детальные строки и добавляет итоговые. Если нужна только сводная таблица для дальнейшей обработки в коде — используйте группировку. Если результат выводится пользователю в виде дерева — итоги.
Сравнение вариантов
Возвращает плоскую сводную таблицу. Подходит для расчётов в коде и соединений с другими данными. Нет детальных строк.
Сохраняет детальные строки и добавляет итоговые уровни. Подходит для древовидных отчётов, требует обхода через ВыборкаПоГруппировкам.
Итоги уже рассчитаны платформой. Самый быстрый вариант для оборотов и остатков, но работает только с регистрами.
Суммирует уже полученную таблицу значений. Удобен для небольших таблиц, но требует выгрузки всех данных в память.
Суммирование в коде: Свернуть и цикл по выборке
Если данные уже получены в таблицу значений, просуммировать строки можно без повторного запроса — методом Свернуть(). Он принимает два параметра: строку с именами колонок группировки и строку с именами суммируемых колонок:
ТаблицаРезультат.Свернуть("Контрагент, Склад", "Количество, Сумма");
После свёртки в таблице останется по одной строке на каждую комбинацию «контрагент + склад», а значения колонок «Количество» и «Сумма» будут просуммированы. Остальные колонки при этом удаляются — если они нужны, сворачивать следует копию таблицы через Скопировать().
Альтернативный путь — ручной цикл по выборке с накоплением суммы в переменной. Это оправдано, когда суммирование нужно совместить с дополнительной логикой: условным учётом строк, конвертацией валют, округлением. Но если задача сводится к простому сложению, свёртка или группировка в запросе предпочтительнее — они короче и выполняются быстрее.
Метод Свернуть суммирует только колонки с числовым типом. Если колонка содержит значения составного типа или Null, свёртка может дать неожиданный результат — перед суммированием проверьте типы колонок и при необходимости приведите значения к числу.
Типичные ошибки и проверка результата
Самая распространённая ошибка — забыть включить неагрегатное поле в СГРУППИРОВАТЬ ПО. Конструктор запросов в этом случае не даст сохранить текст, но при ручном редактировании запроса в коде ошибка вылезет только в момент выполнения. Второй частый промах — соединение с другой таблицей после группировки, которое размножает строки и завышает суммы. Если сумма вдруг стала кратно больше ожидаемой, первым делом проверяйте дубли от соединений.
Третья типичная ситуация — сравнение суммы с NULL. Выражение ИМЕЮЩИЕ СУММА(Сумма) > 0 не вернёт группы, где сумма равна NULL, потому что любое сравнение с NULL даёт ложь. Если такие группы нужны, добавьте обработку через ЕСТЬNULL.
Проверять результат суммирования удобно контрольным запросом: выполните выборку без группировки по тем же данным и просуммируйте значения вручную по нескольким группам. Совпадение с агрегированным результатом подтверждает корректность. Для регистров дополнительно сверяйтесь со стандартными отчётами конфигурации — расхождение обычно указывает на неверные параметры периода или отборы.
Как проверить результат
Равно числу уникальных комбинаций полей группировки
Строк больше — группировка не сработала, меньше — потеряны данные
Совпадает с суммой по исходной выборке без группировки
Расходится — есть дубли от соединений или потери из-за отборов
Отображаются как 0 или отсутствуют осознанно
Появляются NULL там, где ожидался ноль
Частые вопросы о суммировании в запросах 1С
Можно ли просуммировать строки без группировки?
Да. Если в запросе указать только СУММА(Поле) без неагрегатных полей и без СГРУППИРОВАТЬ ПО, запрос вернёт одну строку с общей суммой по всей выборке. Это стандартный способ получить единственный итоговый показатель.
Чем СУММА отличается от КОЛИЧЕСТВО?
СУММА складывает числовые значения поля, а КОЛИЧЕСТВО считает число строк или ненулевых значений. Для подсчёта уникальных значений используется КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Поле). Путать их нельзя: сумма количества товара и количество строк с товаром — разные показатели.
Почему СУММА возвращает NULL вместо нуля?
Если все суммируемые значения в группе равны NULL, результатом тоже будет NULL, поскольку функция игнорирует NULL при сложении. Оберните поле в ЕСТЬNULL(Поле, 0) внутри СУММА, чтобы получить нулевой результат.
Как просуммировать данные из двух разных таблиц?
Сначала объедините выборки через ОБЪЕДИНИТЬ ВСЕ во временную таблицу или подзапрос, а затем примените СУММА с группировкой к объединённому результату. Суммировать таблицы по отдельности и складывать итоги тоже можно, но объединение обычно проще и прозрачнее.
Что быстрее: группировка в запросе или Свернуть в коде?
Группировка в запросе почти всегда предпочтительнее: агрегация выполняется на сервере СУБД, а в код передаётся уже компактный результат. Свернуть оправдан, только когда таблица значений уже получена для других целей и повторный запрос не нужен.
Как получить итоги сразу по нескольким уровням группировки?
Используйте ИТОГИ ПО с перечислением полей через запятую, например ИТОГИ СУММА(Сумма) ПО Контрагент, Месяц. Результат обходится в коде через ВыборкаПоГруппировкам с вложенными циклами, а ключевое слово ОБЩИЕ добавит итог по всей выборке.
Что важно запомнить
Строки в запросе 1С суммируются функцией СУММА вместе с СГРУППИРОВАТЬ ПО: все неагрегатные поля должны попасть в группировку. Фильтруйте строки через ГДЕ до группировки, а группы — через ИМЕЮЩИЕ после неё. Для регистров используйте виртуальные таблицы с параметрами, для древовидных отчётов — ИТОГИ ПО, для готовых таблиц значений — Свернуть(). Всегда обрабатывайте NULL через ЕСТЬNULL и проверяйте итоги контрольной выборкой.