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