Как объединить два запроса в языке запросов 1С

· 9 мин

Содержание

Два запроса ставят друг под друга и соединяют оператором ОБЪЕДИНИТЬ или ОБЪЕДИНИТЬ ВСЕ — результаты складываются в одну таблицу по вертикали. Главное условие: в обеих выборках одинаковое число колонок, а соединяются они по порядку следования, не по именам. Имена колонок результата берутся из первого запроса.

ОБЪЕДИНИТЬ убирает полные дубли строк, ОБЪЕДИНИТЬ ВСЕ оставляет всё как есть и работает быстрее. Ниже — синтаксис, выравнивание разных структур, временные таблицы для тяжёлых пакетов и разбор ошибок, на которые натыкаются чаще всего.

Оператор ОБЪЕДИНИТЬ: как он склеивает выборки

Оператор пишется между двумя (или более) выборками ВЫБРАТЬ. Каждая выборка — самостоятельный запрос со своими источниками и условиями, а объединение просто ставит их строки одна под другой.

ВЫБРАТЬ
    Товары.Номенклатура КАК Номенклатура,
    Товары.Количество КАК Количество
ИЗ
    Документ.ПоступлениеТоваров.Товары КАК Товары

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Товары.Номенклатура,
    Товары.Количество
ИЗ
    Документ.РеализацияТоваров.Товары КАК Товары

Три правила, которые нужно держать в голове:

  • 🔢 Число колонок совпадает. В обеих выборках ровно одинаковое количество полей. Три против двух — платформа не соберёт запрос.
  • 📍 Колонки склеиваются по позиции. Первое поле первой выборки ложится в первое поле второй, второе — во второе и так далее. Имена при этом роли не играют.
  • 🏷️ Псевдонимы — из первого запроса. Во втором и следующих запросах КАК можно не писать: алиасы всё равно берутся из первого. Поэтому КАК Номенклатура, КАК Количество задают один раз, наверху.

Объединять можно не только два запроса. Ставьте ОБЪЕДИНИТЬ ВСЕ между любым числом выборок — например, собрать движения из трёх разных документов в один список. Логика та же: все колонки по позиции, имена сверху.

Если в одной позиции окажутся поля разных типов (в первой выборке — число, во второй — строка), 1С не выдаст ошибку, а соберёт в этой колонке составной тип. Иногда это удобно, но чаще это признак того, что поля перепутаны местами.

ОБЪЕДИНИТЬ или ОБЪЕДИНИТЬ ВСЕ — что выбрать

Разница одна, но важная. ОБЪЕДИНИТЬ после склейки проходит по результату и выкидывает полностью одинаковые строки — те, где совпали значения во всех колонках. ОБЪЕДИНИТЬ ВСЕ этого не делает и отдаёт строки как есть.

КритерийОБЪЕДИНИТЬОБЪЕДИНИТЬ ВСЕ
Дубли строкудаляютсяостаются
Скоростьмедленнее (идёт отбор уникальных)быстрее
Когда применятьнужен список уникальных значенийстроки заведомо разные или дубли не мешают

На практике ОБЪЕДИНИТЬ ВСЕ берут по умолчанию и переходят на ОБЪЕДИНИТЬ только тогда, когда дубли действительно надо схлопнуть. Пример для ОБЪЕДИНИТЬ: собрать единый перечень контрагентов, встречающихся и в поступлениях, и в реализациях, — один контрагент в итоге должен быть один раз.

ОБЪЕДИНИТЬ убирает дубли по всем колонкам сразу. Если в выборке есть поле Ссылка или Регистратор, строки почти всегда окажутся уникальными, и удаления дублей не произойдёт — вы получите то же, что и от ОБЪЕДИНИТЬ ВСЕ, только медленнее. Хотите схлопнуть по номенклатуре — убирайте из выборки лишние поля или группируйте результат отдельно.

Как свести запросы с разными полями в одну структуру

Частый случай: выборки описывают разные данные, и набор полей у них не совпадает. Поступление даёт приход, реализация — расход. Чтобы объединить их в одну таблицу «приход-расход», структуру выравнивают — в каждую выборку добавляют недостающие колонки с нулём или пустым значением.

ВЫБРАТЬ
    Товары.Номенклатура КАК Номенклатура,
    Товары.Количество КАК Приход,
    0 КАК Расход
ИЗ
    Документ.ПоступлениеТоваров.Товары КАК Товары

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Товары.Номенклатура,
    0,
    Товары.Количество
ИЗ
    Документ.РеализацияТоваров.Товары КАК Товары

Обратите внимание на порядок: в первой выборке приход на втором месте, ноль-заглушка — на третьем; во второй наоборот. Колонки встают по позиции, поэтому заглушки держат «сетку» ровной.

Когда вместо нуля нужно именно пустое значение с конкретным типом, применяют ВЫРАЗИТЬ:

ВЫРАЗИТЬ(NULL КАК Число(15, 2)) КАК Сумма
ВЫРАЗИТЬ(NULL КАК Дата) КАК ДатаОплаты

Это задаёт колонке точный тип данных вместо «неопределённого» NULL. Без явного типа колонка может получить составной тип, и дальше по ней не выйдет нормально группировать или суммировать.

Для текстовых заглушек работает то же правило — подставляйте пустую строку "" или нужное значение. А если одной выборке не хватает ссылочного поля (скажем, контрагента), ставьте пустую ссылку соответствующего типа через ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка).

Выборка-константа без источника

У ВЫБРАТЬ не обязателен ИЗ. Выборка из одних констант — тоже полноценный запрос, и её можно объединять с остальными. Приём удобен, когда нужно добавить в результат одну-две «ручные» строки или собрать небольшую таблицу-справочник прямо в тексте запроса.

ВЫБРАТЬ
    "Приход" КАК ВидДвижения,
    1 КАК Порядок

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    "Расход",
    2

Так получается таблица из двух строк без обращения к базе. Её часто соединяют с основными данными, чтобы задать порядок вывода или подписи разделов отчёта.

Тот же подход выручает, когда в объединённый список надо добавить строку «Итого» или «Не распределено» — её формируют отдельной выборкой-константой и приклеивают через ОБЪЕДИНИТЬ ВСЕ. Главное — выдержать число и типы колонок: текст к тексту, число к числу, иначе колонка уйдёт в составной тип.

Временные таблицы для сложных объединений

Когда объединяемых выборок много или поверх результата нужны группировка, соединение с другими таблицами и расчёты, запрос становится громоздким. Тут выручают временные таблицы и пакет запросов.

Идея простая: сначала объединённый результат кладут во временную таблицу оператором ПОМЕСТИТЬ, а следующим запросом пакета уже работают с ней — группируют, соединяют, фильтруют.

ВЫБРАТЬ
    Товары.Номенклатура КАК Номенклатура,
    Товары.Количество КАК Приход,
    0 КАК Расход
ПОМЕСТИТЬ ВТ_Движения
ИЗ
    Документ.ПоступлениеТоваров.Товары КАК Товары

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Товары.Номенклатура,
    0,
    Товары.Количество
ИЗ
    Документ.РеализацияТоваров.Товары КАК Товары
;

ВЫБРАТЬ
    ВТ_Движения.Номенклатура КАК Номенклатура,
    СУММА(ВТ_Движения.Приход) КАК Приход,
    СУММА(ВТ_Движения.Расход) КАК Расход
ИЗ
    ВТ_Движения КАК ВТ_Движения
СГРУППИРОВАТЬ ПО
    ВТ_Движения.Номенклатура

Запросы пакета разделяют точкой с запятой ;. В первом объединение сразу уходит в ВТ_Движения, во втором строки по каждой номенклатуре схлопываются в приход и расход.

Если по временной таблице дальше идут соединения или отборы по полю, добавьте индекс — это заметно ускорит пакет:

...
ПОМЕСТИТЬ ВТ_Движения
ИЗ
    ...
ИНДЕКСИРОВАТЬ ПО
    Номенклатура

Со стороны встроенного языка пакет исполняют так. Для чтения только итогового результата хватает обычного Выполнить() — он вернёт результат последнего запроса пакета:

Запрос = Новый Запрос(ТекстПакета);
Результат = Запрос.Выполнить();

Когда временные таблицы нужны и в других запросах, их переживает МенеджерВременныхТаблиц, а результаты всех запросов пакета по отдельности возвращает ВыполнитьПакет():

Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
МассивРезультатов = Запрос.ВыполнитьПакет();

Временную таблицу, которая больше не нужна в пакете, освобождают оператором УНИЧТОЖИТЬ ВТ_Движения. На небольших выборках это необязательно, но на крупных помогает не держать лишнее в памяти менеджера.

Порядок, итоги и группировка поверх объединённого результата

Сортировка и итоги применяются ко всему объединению сразу, а не к каждой выборке. Поэтому УПОРЯДОЧИТЬ ПО пишется один раз — в самом конце, после последней выборки:

ВЫБРАТЬ ...
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ ...

УПОРЯДОЧИТЬ ПО
    Номенклатура

Поставить УПОРЯДОЧИТЬ ПО внутри отдельной выборки объединения нельзя — платформа такой запрос не соберёт. То же с ИТОГИ: они считаются по общему результату и указываются в конце.

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

Производительность: чтобы объединение не тормозило

Несколько приёмов, которые реально влияют на скорость:

  1. 🚀 По умолчанию — ОБЪЕДИНИТЬ ВСЕ. Отказ от удаления дублей снимает лишний проход по результату. ОБЪЕДИНИТЬ без «ВСЕ» ставьте только когда дубли действительно надо убрать.
  2. 🧹 Фильтруйте в каждой выборке. Условия ГДЕ лучше ставить внутри объединяемых запросов, до склейки, — так в объединение попадёт меньше строк.
  3. 🧩 Избегайте составных типов в колонках. Если в одной позиции встречаются поля разных типов, результат получает составной тип — это замедляет и объединение, и последующие соединения. Приводите поля к одному типу через ВЫРАЗИТЬ.
  4. 🗂️ Индексируйте временные таблицы. Если по результату объединения идут соединения или отборы, ИНДЕКСИРОВАТЬ ПО по полям связи ускоряет пакет в разы.
  5. ✂️ Не тащите лишние поля. Каждая колонка — это данные, которые читаются и сравниваются. Выбирайте только то, что нужно в результате.

Объединение само по себе дешёвое, дорогими бывают выборки под ним. Если запрос тормозит, сначала проверьте, что каждая выборка использует индексы и не сканирует таблицу целиком, а уже потом оптимизируйте саму склейку.

Типичные ошибки объединения и как их исправить

Диагностика: выберите симптом

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

Ещё одна тонкая ошибка — ждать, что ОБЪЕДИНИТЬ отсортирует или сгруппирует данные сам. Он только складывает строки. Любые итоги, сортировка и схлопывание по ключу — это отдельные операции поверх результата, и делать их надо явно.

Проверьте себя

Проверьте себя
Соединяются ли колонки при объединении по имени?
Что оставляет в результате ОБЪЕДИНИТЬ ВСЕ?
Где ставится УПОРЯДОЧИТЬ ПО в объединённом запросе?

Частые вопросы

Сколько запросов можно объединить за раз?
Ограничения на два нет. Ставьте ОБЪЕДИНИТЬ ВСЕ между любым числом выборок — главное, чтобы у всех совпадало число колонок и порядок полей.
Сохраняется ли порядок строк после объединения?
Нет. Без УПОРЯДОЧИТЬ ПО порядок строк не гарантирован — платформа может отдать их в любой последовательности. Нужна сортировка — задавайте её явно в конце запроса.
Чем объединение отличается от соединения (СОЕДИНЕНИЕ)?
Объединение складывает строки по вертикали — результаты идут один под другим. Соединение (ВНУТРЕННЕЕ/ЛЕВОЕ СОЕДИНЕНИЕ) связывает таблицы по горизонтали, по условию совпадения полей. Это разные задачи.
Почему пропадают строки при ОБЪЕДИНИТЬ?
ОБЪЕДИНИТЬ без «ВСЕ» удаляет полностью совпадающие строки. Если строки должны остаться, используйте ОБЪЕДИНИТЬ ВСЕ.
Можно ли объединять виртуальные таблицы регистров?
Да, выборка из виртуальной таблицы (Остатки, ОстаткиИОбороты и т. п.) участвует в объединении на общих правах — важно лишь выровнять набор и порядок колонок с остальными выборками.