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