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