К статье
Практический материал

Разработка и Конфигурация · 13 мин

Группировка в запросе 1С: как работает и когда нужна

Что такое группировка в запросе 1С, как работает СГРУППИРОВАТЬ ПО, агрегатные функции, ИТОГИ, типичные ошибки и примеры кода для разработчика.

Группировка в запросе 1С — это способ объединить множество строк данных в сводные строки по значениям одного или нескольких полей, применив к каждой группе агрегатные функции: сумму, количество, среднее, минимум или максимум. Вместо тысячи строк по каждой продаже вы получаете одну строку на каждого контрагента с итоговой суммой продаж. Для этого в языке запросов 1С используется конструкция СГРУППИРОВАТЬ ПО (английский синтаксис — GROUP BY).

Без группировки запрос возвращает детальные записи «как есть»: каждый документ, каждая строка табличной части, каждое движение регистра. Это удобно для выгрузки деталей, но непригодно для аналитики. Менеджеру не нужен список из 10 000 проводок — ему нужен оборот по каждому счёту. Группировка выполняет эту свёртку на стороне СУБД, не загружая лишние данные в память сервера 1С.

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

Как устроена конструкция СГРУППИРОВАТЬ ПО

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

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

ВЫБРАТЬ

Продажи.Контрагент КАК Контрагент,

СУММА(Продажи.Сумма) КАК СуммаПродаж

ИЗ

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

ГДЕ

Продажи.Проведен

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

Продажи.Контрагент

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

Группировать можно по нескольким полям — тогда группа образуется по уникальной комбинации значений. Например, СГРУППИРОВАТЬ ПО Контрагент, Период даст строку на каждую пару «контрагент + месяц». Порядок полей в группировке влияет только на читаемость, а не на результат: комбинации считаются по всему набору полей целиком.

Агрегатные функции: что доступно и как себя ведут

Язык запросов 1С поддерживает стандартный набор агрегатных функций: СУММА, КОЛИЧЕСТВО, СРЕДНЕЕ, МИНИМУМ, МАКСИМУМ. Функция КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Поле) считает количество уникальных значений — например, число разных номенклатурных позиций в продажах клиента.

Ключевой нюанс — поведение с NULL. Агрегатные функции игнорируют значения NULL: СРЕДНЕЕ по полю, где часть строк пустая, посчитает среднее только по заполненным. КОЛИЧЕСТВО(Поле) не учитывает NULL-строки, тогда как КОЛИЧЕСТВО(*) считает все строки группы без исключения. Если при соединении таблиц (например, левом) часть полей может быть NULL, суммы и средние нужно проверять отдельно.

Ещё одна тонкость: СУММА по полю с типом «число» и по полю составного типа может вернуть разный тип результата, а при левом соединении без совпадений сумма вернёт NULL, а не ноль. Если дальше в коде вы планируете складывать результат, оберните его в ЕСТЬNULL(СУММА(...), 0) уже на уровне запроса — это избавит от проверок типов в обходе выборки.

ФункцияЧто возвращаетТипичное применение
СУММА(Поле)Сумма значений группыОбороты, суммы продаж, остатки
КОЛИЧЕСТВО(*)Число строк в группеКоличество документов, строк движений
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Поле)Число уникальных значенийЧисло клиентов, позиций номенклатуры
СРЕДНЕЕ(Поле)Среднее без учёта NULLСредний чек, средняя цена
МИНИМУМ / МАКСИМУМКрайние значения группыПервая/последняя дата, мин/макс цена

Фильтрация групп: чем ИМЕЮЩИЕ отличается от ГДЕ

Условие ГДЕ отбирает строки до группировки — то есть фильтрует исходные детальные данные. Если нужно отфильтровать уже сгруппированный результат, используется секция ИМЕЮЩИЕ (англ. HAVING). Классический пример: выбрать контрагентов, у которых сумма продаж превысила порог.

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

Продажи.Контрагент

ИМЕЮЩИЕ

СУММА(Продажи.Сумма) > 100000

Разница принципиальна для результата и производительности. Условие «контрагент не помечен на удаление» относится к ГДЕ — оно сокращает объём данных до агрегации. Условие «сумма больше 100 000» можно вычислить только после группировки, поэтому оно идёт в ИМЕЮЩИЕ. Если по ошибке перенести агрегатное условие в ГДЕ, запрос не выполнится: агрегатные функции в секции ГДЕ запрещены.

В ИМЕЮЩИЕ допустимы и условия без агрегатных функций — по полям группировки. Но с точки зрения производительности такие условия лучше переносить в ГДЕ: чем раньше отсечены лишние строки, тем меньше данных обрабатывает СУБД.

Группировка или ИТОГИ: в чём разница и что выбрать

Конструкция ИТОГИ ПО не заменяет группировку, а работает по-другому: запрос возвращает все детальные строки, а при обходе результата с типом обхода ПоГруппировкам вы получаете промежуточные итоговые записи по указанным измерениям. Детальные данные остаются доступными.

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

Сравнение вариантов

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

Возвращает только сводные строки. Быстрее и легче по памяти. Подходит, когда детали не нужны.

ИТОГИ ПО

Возвращает детали плюс итоговые записи при обходе ПоГруппировкам. Подходит для отчётов с расшифровкой, но результат объёмнее.

СКД (компоновка данных)

Группировки задаются настройками отчёта без изменения текста запроса. Оптимально для пользовательских отчётов с гибкой структурой.

Частая ситуация: разработчик пишет запрос с ИТОГИ ПО, а потом в цикле вручную суммирует детальные строки, игнорируя итоговые записи. Это признак того, что нужна была обычная группировка — запрос можно упростить и ускорить.

Типичные ошибки при работе с группировкой

Первая и самая частая ошибка — поле в выборке вне группировки и вне агрегатной функции. Платформа прямо сообщает об этом, но новички иногда «лечат» проблему, добавляя лишнее поле в СГРУППИРОВАТЬ ПО. Это меняет результат: вместо одной строки на контрагента появляется строка на каждую комбинацию, и суммы в отчёте «расползаются» по строкам.

Вторая ошибка — группировка по ссылке вместо реквизита. Если сгруппировать по полю Контрагент (ссылка), две разные ссылки с одинаковым наименованием дадут две строки. Если нужна группировка по названию — группируйте по Контрагент.Наименование, но помните, что обращение через точку к реквизиту («разыменование») в больших таблицах может замедлить запрос.

Третья группа проблем — NULL и дубли при соединениях. Если перед группировкой таблица соединяется с другой по неуникальному ключу, строки задваиваются, и СУММА честно складывает дубли. Симптом: итоги в отчёте больше реальных кратно числу совпадений. Лечение — сначала сгруппировать или убрать дубли во временной таблице, потом соединять.

Типичные ошибки
01
Добавление лишнего поля в СГРУППИРОВАТЬ ПО ради устранения ошибки — результат дробится на лишние строки
02
Суммирование после соединения с дублями — итоги завышены кратно числу совпадений
03
Игнорирование NULL: сумма возвращает NULL вместо 0, код падает при арифметике
04
Использование ИТОГИ ПО там, где достаточно СГРУППИРОВАТЬ ПО — лишний объём данных и медленный обход
05
Условие по агрегатной функции в секции ГДЕ вместо ИМЕЮЩИЕ — запрос не выполняется

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

Группировка выполняется на стороне СУБД и сама по себе операция не тяжёлая — тяжёлым бывает объём данных, который приходится агрегировать. Основной приём оптимизации: отсекать лишнее до группировки. Условия по периоду, организации, складу в секции ГДЕ могут сократить выборку в десятки раз.

Группировка по полям виртуальных таблиц регистров (например, РегистрНакопления.Продажи.Обороты) обычно эффективнее, чем группировка детальной таблицы движений: виртуальная таблица оборотов уже хранит предрасчитанные итоги. Если нужны обороты по измерениям регистра — сначала проверьте, не решает ли задачу готовая виртуальная таблица.

Избегайте группировки по выражениям с функциями (например, ПОДСТРОКА или обращение через точку к реквизитам ссылок) на больших таблицах — такие выражения не используют индексы и заставляют СУБД вычислять значение для каждой строки. Лучше вынести вычисление во временную таблицу или пересмотреть структуру запроса.

Порядок действий при построении группировки
  1. 1
    Определите, какие сводные данные нужны: по каким полям группировать и что считать (сумма, количество)
  2. 2
    Отберите минимально необходимые строки условиями в секции ГДЕ — период, организация, проведённые документы
  3. 3
    Перечислите поля группировки в СГРУППИРОВАТЬ ПО, остальные поля оберните агрегатными функциями
  4. 4
    Добавьте условия по результатам агрегации в ИМЕЮЩИЕ, если нужно отфильтровать группы
  5. 5
    Выполните запрос в консоли запросов и сверьте итоги с эталонным отчётом конфигурации

Проверка результата и границы самостоятельной работы

Проверять группировку удобнее всего в консоли запросов на копии базы или на тестовом периоде. Контрольный приём: сравнить общую сумму сгруппированного результата с суммой по детальному запросу без группировки — они обязаны совпасть. Если сгруппированный итог больше, ищите дубли в соединениях; если меньше — проверяйте условия и потерю строк с NULL.

Для отчётов на СКД дополнительная проверка — сверка с типовым отчётом конфигурации (например, оборотно-сальдовой ведомостью или отчётом по продажам). Расхождение с типовым отчётом почти всегда означает ошибку в логике запроса, а не в данных.

Группировка в запросе — безопасная операция: она только читает данные и ничего не изменяет в базе. Риск появляется в другом месте: когда результаты запроса используются для записи — проведения документов, расчёта себестоимости, переноса остатков. Ошибочная группировка в такой цепочке приведёт к неверным данным в учёте. Поэтому любые запросы, чей результат записывается в базу, сначала отлаживайте на копии и сверяйте цифры до загрузки.

Контрольные точки

Как проверить результат

Сумма сгруппированного результата против суммы детальных строк
Норма

Итоги совпадают до копейки

Тревожный признак

Сгруппированная сумма больше — вероятны дубли после соединения

Количество строк результата
Норма

Число строк равно числу уникальных комбинаций полей группировки

Тревожный признак

Строк заметно больше — в группировку попало лишнее поле

Значения сумм в строках
Норма

Числа вместо NULL, типы соответствуют ожиданиям

Тревожный признак

NULL в суммах — нужен ЕСТЬNULL или проверка соединений

Если запрос с группировкой выполняется неприемлемо долго даже после сужения периода и проверки соединений — это повод привлечь специалиста по оптимизации: анализ плана запроса, индексов и структуры регистров требует опыта работы с конкретной СУБД (MS SQL, PostgreSQL) и консолью СУБД, а не только конфигуратора.

Частые вопросы о группировке в запросах 1С

Чем СГРУППИРОВАТЬ ПО отличается от ИТОГИ ПО?

СГРУППИРОВАТЬ ПО физически сворачивает строки: в результате остаются только сводные записи. ИТОГИ ПО сохраняет все детальные строки и лишь добавляет итоговые записи, доступные при обходе результата с типом «ПоГруппировкам». Для чистой аналитики берите группировку, для отчётов с расшифровкой — итоги или СКД.

Почему запрос выдаёт ошибку «Поле не входит в группу»?

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

Почему СУММА после группировки больше реальной?

Почти всегда причина — дубли строк, возникшие при соединении таблиц до группировки. Если к одной строке основной таблицы присоединяется несколько строк второй, сумма умножается. Решение: сгруппировать или свернуть присоединяемые данные во временной таблице до соединения.

Можно ли группировать по периоду — месяцу или дню?

Да. Используйте функции работы с датами: НАЧАЛОПЕРИОДА(Дата, МЕСЯЦ) в выборке и в группировке даст строку на каждый месяц. В виртуальных таблицах регистров часто есть готовое поле Период с заданной периодичностью — его можно группировать напрямую.

Что быстрее: группировка в запросе или суммирование в цикле на встроенном языке?

Группировка в запросе практически всегда быстрее: агрегация выполняется СУБД, и на сервер 1С передаётся только сводный результат. Цикл по детальной выборке с ручным суммированием гоняет лишние данные и выполняется медленнее, особенно на больших объёмах.

Работает ли группировка в запросах к табличным частям документов?

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

Итог

Что важно запомнить

Группировка через СГРУППИРОВАТЬ ПО сворачивает строки по уникальным комбинациям полей и применяет агрегатные функции к остальным колонкам. Каждое поле выборки — либо в группировке, либо в агрегатной функции. Фильтруйте строки в ГДЕ, группы — в ИМЕЮЩИЕ. Проверяйте итоги сверкой с детальными данными и остерегайтесь дублей после соединений.