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