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