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

В этой статье мы разберем 5 основных способов получения итогов в запросах 1С 8.3 — от элементарного использования функции СУММА() до сложных многоуровневых группировок с условиями. Особое внимание уделим типичным ошибкам, которые приводят к искажению данных, и покажем, как их избежать. Все примеры приведены с учетом синтаксиса последних версий платформы и протестированы на реальных конфигурациях.

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

⚠️ Внимание: Синтаксис функций агрегации (СУММА(), КОЛИЧЕСТВО() и др.) может незначительно отличаться в разных версиях 1С:Предприятие. Например, в 1С 7.7 использовался другой подход к группировке. Все примеры в статье актуальны для 1С 8.3.20+.

1. Базовые функции для расчета итогов: СУММА, КОЛИЧЕСТВО, МАКСИМУМ

Начнем с самого простого — встроенных функций агрегации, которые позволяют получить итоговые значения по числовым полям. Эти функции работают внутри оператора ВЫБРАТЬ и автоматически рассчитывают результат по всем строкам выборки (или по группам, если используется СГРУППИРОВАТЬ ПО).

Самые востребованные функции:

  • 📊 СУММА(Поле) — возвращает сумму значений числового поля. Пример: СУММА(ДокументСклад.СуммаДокумента).
  • 🔢 КОЛИЧЕСТВО(Поле) — подсчитывает количество строк (в том числе с NULL, если указать КОЛИЧЕСТВО(*)).
  • ⬆️ МАКСИМУМ(Поле) / МИНИМУМ(Поле) — находят крайние значения.
  • СРЕДНЕЕ(Поле) — вычисляет среднее арифметическое (игнорирует NULL).

Пример запроса, который выводит общую сумму и количество документов за месяц:

ВЫБРАТЬ

СУММА(Документ.СуммаДокумента) КАК ОбщаяСумма,

КОЛИЧЕСТВО(*) КАК КоличествоДокументов

ИЗ

Документ.РеализацияТоваровУслуг КАК Документ

ГДЕ

Документ.Дата МЕЖДУ &НачалоМесяца И &КонецМесяца

Важный нюанс: если в выборке есть поля с типом Булево или Дата, функции СУММА() или СРЕДНЕЕ() к ним применять нельзя — это вызовет ошибку. Для дат используйте МАКСИМУМ()/МИНИМУМ(), а для булевых полей — КОЛИЧЕСТВО() с условием.

📊 Какую функцию агрегации вы используете чаще всего?
СУММА
КОЛИЧЕСТВО
МАКСИМУМ/МИНИМУМ
СРЕДНЕЕ
Другую

2. Группировка данных: оператор СГРУППИРОВАТЬ ПО

Чтобы получить итоги не по всей выборке, а по группам (например, сумму продаж по каждому контрагенту или количество товаров по складам), используется оператор СГРУППИРОВАТЬ ПО. Он разбивает результат запроса на группы по указанным полям и рассчитывает итоги для каждой группы отдельно.

Синтаксис:

ВЫБРАТЬ

ПолеДляГруппировки1,

ПолеДляГруппировки2,

АгрегатнаяФункция(ПолеДляИтога) КАК ИтоговоеПоле

ИЗ

Таблица

СГРУППИРОВАТЬ ПО

ПолеДляГруппировки1,

ПолеДляГруппировки2

Пример: получим сумму реализации по каждому контрагенту за квартал:

ВЫБРАТЬ

Документ.Контрагент КАК Контрагент,

СУММА(Документ.СуммаДокумента) КАК СуммаПродаж

ИЗ

Документ.РеализацияТоваровУслуг КАК Документ

ГДЕ

Документ.Дата МЕЖДУ &НачалоКвартала И &КонецКвартала

СГРУППИРОВАТЬ ПО

Документ.Контрагент

Типичная ошибка: если в операторе ВЫБРАТЬ указано поле, которое не входит ни в СГРУППИРОВАТЬ ПО, ни в агрегатную функцию, запрос завершится ошибкой. Например, так нельзя:

ВЫБРАТЬ

Документ.Контрагент,

Документ.Дата, // ← ОШИБКА: дата не сгруппирована и не агрегирована!

СУММА(Документ.СуммаДокумента)

💡

Если нужно вывести дополнительные поля без группировки (например, максимальную дату в группе), используйте вложенный запрос или функцию МАКСИМУМ(Документ.Дата).

3. Многоуровневая группировка: итоги по нескольким полям

В реальных отчетах часто требуется группировать данные по нескольким критериям одновременно. Например, сначала по организациям, затем по контрагентам, а внутри — по видам договоров. Для этого поля в СГРУППИРОВАТЬ ПО перечисляются через запятую в порядке вложенности.

Пример: итоги продаж по организациям и контрагентам:

ВЫБРАТЬ

Документ.Организация КАК Организация,

Документ.Контрагент КАК Контрагент,

СУММА(Документ.СуммаДокумента) КАК СуммаПродаж,

КОЛИЧЕСТВО(*) КАК КоличествоДокументов

ИЗ

Документ.РеализацияТоваровУслуг КАК Документ

ГДЕ

Документ.Дата МЕЖДУ &НачалоГода И &КонецГода

СГРУППИРОВАТЬ ПО

Документ.Организация,

Документ.Контрагент

Результат будет выглядеть так:

ОрганизацияКонтрагентСумма продажКоличество документов
ООО "Ромашка"ИП Иванов450 00012
ООО "Ромашка"ООО "Тюльпан"1 200 00034
ООО "Ландыш"ИП Петров780 00018

Особенность: порядок полей в СГРУППИРОВАТЬ ПО влияет на структуру результата. Если поменять местами Организация и Контрагент, итоги будут сгруппированы сначала по контрагентам, а внутри — по организациям. Это критично для отчетов с иерархией (например, сводные таблицы).

Как избежать дублирования строк при многоуровневой группировке?

Если в результате появляются дублирующиеся строки (например, из-за связей "многие ко многим"), используйте конструкцию РАЗЛИЧНЫЕ перед полями группировки:

СГРУППИРОВАТЬ ПО РАЗЛИЧНЫЕ

Документ.Организация,

Документ.Контрагент

Это устранит дубли, но может повлиять на производительность при больших объемах данных.

4. Итоги с условиями: операторы ГДЕ и ИМЕЮЩИЕ

Иногда требуется рассчитать итоги не по всем данным, а только по тем, которые удовлетворяют определенным условиям. Для этого используются два оператора:

  • 🔍 ГДЕ — фильтрует строки до группировки (уменьшает объем обрабатываемых данных).
  • 📌 ИМЕЮЩИЕ — фильтрует группы после группировки (применяется к итогам).

Пример с ГДЕ: сумма продаж только по оптовым контрагентам:

ВЫБРАТЬ

Документ.Контрагент КАК Контрагент,

СУММА(Документ.СуммаДокумента) КАК СуммаПродаж

ИЗ

Документ.РеализацияТоваровУслуг КАК Документ

ГДЕ

Документ.ВидДоговора = ЗНАЧЕНИЕ(Перечисление.ВидыДоговоров.Оптовый)

И Документ.Дата МЕЖДУ &НачалоГода И &КонецГода

СГРУППИРОВАТЬ ПО

Документ.Контрагент

Пример с ИМЕЮЩИЕ: выведем только тех контрагентов, у которых сумма продаж превышает 1 млн рублей:

ВЫБРАТЬ

Документ.Контрагент КАК Контрагент,

СУММА(Документ.СуммаДокумента) КАК СуммаПродаж

ИЗ

Документ.РеализацияТоваровУслуг КАК Документ

ГДЕ

Документ.Дата МЕЖДУ &НачалоГода И &КонецГода

СГРУППИРОВАТЬ ПО

Документ.Контрагент

ИМЕЮЩИЕ

СУММА(Документ.СуммаДокумента) > 1000000

⚠️ Внимание: Оператор ИМЕЮЩИЕ нельзя использовать без СГРУППИРОВАТЬ ПО. Если нужно отфильтровать итоги по всей выборке (без группировки), используйте вложенный запрос или временную таблицу.

5. Вложенные итоги и подзапросы

Для сложных отчетов, где требуется рассчитать итоги на основе других итогов (например, доля продаж контрагента в общем объеме), применяются вложенные запросы или общие табличные выражения (ОБЪЕДИНИТЬ ВСЕ, СОЕДИНИТЬ). Это позволяет избежать дублирования кода и улучшает читаемость.

Пример: рассчитаем долю каждого контрагента в общей сумме продаж:

ВЫБРАТЬ

ИтогиПоКонтрагентам.Контрагент,

ИтогиПоКонтрагентам.СуммаПродаж,

ИтогиПоКонтрагентам.СуммаПродаж / ОбщаяСумма.ОбщаяСумма * 100 КАК ДоляПроцентов

ИЗ

(

ВЫБРАТЬ

Документ.Контрагент КАК Контрагент,

СУММА(Документ.СуммаДокумента) КАК СуммаПродаж

ИЗ

Документ.РеализацияТоваровУслуг КАК Документ

ГДЕ

Документ.Дата МЕЖДУ &НачалоГода И &КонецГода

СГРУППИРОВАТЬ ПО

Документ.Контрагент

) КАК ИтогиПоКонтрагентам,

(

ВЫБРАТЬ

СУММА(Документ.СуммаДокумента) КАК ОбщаяСумма

ИЗ

Документ.РеализацияТоваровУслуг КАК Документ

ГДЕ

Документ.Дата МЕЖДУ &НачалоГода И &КонецГода

) КАК ОбщаяСумма

Альтернативный подход: вместо вложенных запросов можно использовать временные таблицы (оператор ПОМЕСТИТЬ), если запрос выполняется в модуле :

ПОМЕСТИТЬ ВТ_Итоги

ВЫБРАТЬ

Документ.Контрагент КАК Контрагент,

СУММА(Документ.СуммаДокумента) КАК СуммаПродаж

ИЗ

Документ.РеализацияТоваровУслуг КАК Документ

ГДЕ

Документ.Дата МЕЖДУ &НачалоГода И &КонецГода

СГРУППИРОВАТЬ ПО

Документ.Контрагент;

ВЫБРАТЬ

ВТ_Итоги.Контрагент,

ВТ_Итоги.СуммаПродаж,

ВТ_Итоги.СуммаПродаж / (ВЫБРАТЬ СУММА(ВТ_Итоги.СуммаПродаж) ИЗ ВТ_Итоги) * 100 КАК ДоляПроцентов

ИЗ

ВТ_Итоги КАК ВТ_Итоги;

🔹 Убедитесь, что во вложенном запросе есть все необходимые поля для соединения

🔹 Проверьте, что типы данных совпадают (например, не сравнивайте Строка с Число)

🔹 Используйте псевдонимы (КАК) для удобства чтения

🔹 Тестируйте запрос пошагово: сначала внешний, затем внутренний-->

6. Специальные функции для работы с датами и периодами

При расчете итогов по временным интервалам (месяцы, кварталы, годы) полезны специализированные функции:

  • 📅 НАЧАЛОПЕРИОДА(Дата, Месяц/Квартал/Год) — приводит дату к началу периода.
  • 🗓️ РАЗНОСТЬДАТ(Дата1, Дата2, День/Месяц/Год) — рассчитывает разницу между датами.
  • 🔄 ДОБАВИТЬКДАТЕ(Дата, Интервал, День/Месяц/Год) — сдвигает дату на заданный интервал.

Пример: итоги продаж по месяцам с указанием названия месяца:

ВЫБРАТЬ

НАЧАЛОПЕРИОДА(Документ.Дата, Месяц) КАК Период,

ФОРМАТ(НАЧАЛОПЕРИОДА(Документ.Дата, Месяц), "ММММ йййй") КАК НазваниеМесяца,

СУММА(Документ.СуммаДокумента) КАК СуммаПродаж

ИЗ

Документ.РеализацияТоваровУслуг КАК Документ

ГДЕ

Документ.Дата МЕЖДУ &НачалоГода И &КонецГода

СГРУППИРОВАТЬ ПО

НАЧАЛОПЕРИОДА(Документ.Дата, Месяц)

Практический совет: для анализа динамики (например, сравнение с прошлым месяцем) используйте конструкцию с СОЕДИНИТЬ:

ВЫБРАТЬ

ТекущийМесяц.Период,

ТекущийМесяц.СуммаПродаж КАК ТекущаяСумма,

ПрошлыйМесяц.СуммаПродаж КАК ПредыдущаяСумма,

(ТекущийМесяц.СуммаПродаж - ПрошлыйМесяц.СуммаПродаж) / ПрошлыйМесяц.СуммаПродаж * 100 КАК ИзменениеПроцентов

ИЗ

(

ВЫБРАТЬ

НАЧАЛОПЕРИОДА(Документ.Дата, Месяц) КАК Период,

СУММА(Документ.СуммаДокумента) КАК СуммаПродаж

ИЗ

Документ.РеализацияТоваровУслуг КАК Документ

ГДЕ

Документ.Дата МЕЖДУ &НачалоГода И &КонецГода

СГРУППИРОВАТЬ ПО

НАЧАЛОПЕРИОДА(Документ.Дата, Месяц)

) КАК ТекущийМесяц

ЛЕВОЕ СОЕДИНЕНИЕ (

ВЫБРАТЬ

НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(Документ.Дата, Месяц, -1), Месяц) КАК Период,

СУММА(Документ.СуммаДокумента) КАК СуммаПродаж

ИЗ

Документ.РеализацияТоваровУслуг КАК Документ

ГДЕ

Документ.Дата МЕЖДУ ДОБАВИТЬКДАТЕ(&НачалоГода, Год, -1) И ДОБАВИТЬКДАТЕ(&КонецГода, Год, -1)

СГРУППИРОВАТЬ ПО

НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(Документ.Дата, Месяц, -1), Месяц)

) КАК ПрошлыйМесяц ПО ТекущийМесяц.Период = ПрошлыйМесяц.Период

⚠️ Внимание: При работе с датами в условиях (ГДЕ) всегда используйте функции НАЧАЛОДНЯ() или КОНЕЦДНЯ(), чтобы избежать проблем с временем. Например, условие Дата = &ТекущаяДата может не сработать, если в поле хранится дата+время.

7. Динамическое формирование группировок (на стороне 1С)

В некоторых случаях структуру группировки нужно определять динамически — например, в зависимости от настроек отчета или прав пользователя. Для этого в используется механизм программного формирования текста запроса с помощью строковых шаблонов.

Пример: группировка по контрагенту или по организации в зависимости от параметра:

ТекстЗапроса = "

|ВЫБРАТЬ

| Документ." + ?(Параметры.ГруппироватьПоКонтрагенту, "Контрагент", "Организация") + " КАК Группа,

| СУММА(Документ.СуммаДокумента) КАК СуммаПродаж

|ИЗ

| Документ.РеализацияТоваровУслуг КАК Документ

|ГДЕ

| Документ.Дата МЕЖДУ &НачалоПериода И &КонецПериода

|СГРУППИРОВАТЬ ПО

| Документ." + ?(Параметры.ГруппироватьПоКонтрагенту, "Контрагент", "Организация");

Запрос = Новый Запрос(ТекстЗапроса);

Запрос.УстановитьПараметр("НачалоПериода", НачалоМесяца(ТекущаяДата()));

Запрос.УстановитьПараметр("КонецПериода", КонецМесяца(ТекущаяДата()));

Результат = Запрос.Выполнить();

Преимущества подхода:

  • 🔧 Гибкость: один запрос адаптируется под разные сценарии.
  • 📈 Производительность: нет необходимости писать несколько похожих запросов.
  • 🔒 Безопасность: параметры экранируются автоматически (в отличие от прямой подстановки строк).

Риски: при динамическом формировании запросов легко допустить синтаксические ошибки. Всегда проверяйте итоговый текст запроса через Запрос.Текст перед выполнением.

💡

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

8. Оптимизация запросов с итогами: индексы и план выполнения

Запросы с группировкой и агрегатными функциями могут работать медленно на больших объемах данных. Чтобы ускорить их выполнение:

  • 🚀 Создайте индексы по полям, используемым в ГДЕ и СГРУППИРОВАТЬ ПО.
  • 📊 Используйте ИНДЕКСИРОВАТЬ ПО для временных таблиц (в 1С 8.3.14+).
  • 🔍 Просматривайте план выполнения запроса через Запрос.ПланВопроса().
  • 🗑️ Избегайте ВЫБРАТЬ РАЗЛИЧНЫЕ без необходимости — это ресурсоемкая операция.

Пример оптимизированного запроса с указанием индекса:

ВЫБРАТЬ

Документ.Контрагент КАК Контрагент,

СУММА(Документ.СуммаДокумента) КАК СуммаПродаж

ИЗ

Документ.РеализацияТоваровУслуг КАК Документ

ГДЕ

Документ.Дата МЕЖДУ &НачалоПериода И &КонецПериода

И Документ.Организация = &Организация

СГРУППИРОВАТЬ ПО

Документ.Контрагент

ИНДЕКСИРОВАТЬ ПО

Контрагент

Совет по индексам: в конфигураторе проверьте, какие индексы уже созданы для таблиц. Например, для документа РеализацияТоваровУслуг обычно есть индексы по дате и организации. Добавляйте новые индексы только если они реально нужны — избыточная индексация замедляет запись данных.

⚠️ Внимание: Оптимизация запросов — это компромисс между скоростью выполнения и нагрузкой на сервер. Настройку индексов лучше проводить в нерабочее время и тестировать на копии базы.
Как получить итоги по нескольким таблицам одновременно?

Используйте оператор ОБЪЕДИНИТЬ (для вертикального объединения) или СОЕДИНИТЬ (для горизонтального). Пример с ОБЪЕДИНИТЬ:

ВЫБРАТЬ

"Реализация" КАК ТипДокумента,

Документ.Контрагент,

СУММА(Документ.СуммаДокумента) КАК Сумма

ИЗ

Документ.РеализацияТоваровУслуг КАК Документ

ГДЕ

Документ.Дата МЕЖДУ &НачалоПериода И &КонецПериода

СГРУППИРОВАТЬ ПО

Документ.Контрагент

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ

"Поступление" КАК ТипДокумента,

Документ.Контрагент,

СУММА(Документ.СуммаДокумента) * -1 КАК Сумма

ИЗ

Документ.ПоступлениеТоваровУслуг КАК Документ

ГДЕ

Документ.Дата МЕЖДУ &НачалоПериода И &КонецПериода

СГРУППИРОВАТЬ ПО

Документ.Контрагент

Для СОЕДИНИТЬ используйте ключевые поля (например, Контрагент) для связывания таблиц.

Можно ли получить итоги без группировки?

Да, если нужно рассчитать общий итог по всей выборке, просто используйте агрегатные функции без СГРУППИРОВАТЬ ПО:

ВЫБРАТЬ

СУММА(Документ.СуммаДокумента) КАК ОбщаяСумма

ИЗ

Документ.РеализацияТоваровУслуг КАК Документ

Это вернет одну строку с суммой по всем документам.

Как вывести итоги с детализацией (например, список документов в группе)?

Используйте конструкцию ВЫБРАТЬ РАЗРЕШЕННЫЕ или вложенный запрос с В(.... Пример:

ВЫБРАТЬ

Документ.Контрагент КАК Контрагент,

СУММА(Документ.СуммаДокумента) КАК СуммаПродаж,

(ВЫБРАТЬ ПЕРВЫЕ 5

Документ.Номер КАК НомерДокумента

ИЗ

Документ.РеализацияТоваровУслуг КАК Документ2

ГДЕ

Документ2.Контрагент = Документ.Контрагент

УПОРЯДОЧИТЬ ПО

Документ2.Дата УБЫВ

) КАК ТопДокументов

ИЗ

Документ.РеализацияТоваровУслуг КАК Документ

СГРУППИРОВАТЬ ПО

Документ.Контрагент

Обратите внимание: такой подход работает только в 1С 8.3.10+.