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

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

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

Разбираем, как объединить результаты запросов в 1С: ОБЪЕДИНИТЬ и ОБЪЕДИНИТЬ ВСЕ, пакетные запросы, соединение таблиц, типичные ошибки и проверка результата.

Задача объединить результаты запросов в 1С возникает постоянно: нужно вывести в один отчёт остатки по нескольким складам, собрать обороты из разных регистров или склеить данные справочников с одинаковой структурой. В языке запросов 1С для этого есть несколько механизмов, и выбор между ними напрямую влияет на состав итоговой выборки: где-то дубли строк сохраняются, где-то удаляются, а где-то данные не складываются вертикально, а сопоставляются горизонтально.

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

Чем ОБЪЕДИНИТЬ отличается от ОБЪЕДИНИТЬ ВСЕ

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

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

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

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

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

ВЫБРАТЬ

Продажи.Номенклатура КАК Номенклатура,

Продажи.СуммаОборот КАК Сумма

ИЗ

РегистрНакопления.Продажи.Обороты КАК Продажи

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

ВЫБРАТЬ

Закупки.Номенклатура,

-Закупки.СуммаОборот

ИЗ

РегистрНакопления.Закупки.Обороты КАК Закупки

Если типы полей не совпадают (например, в первом запросе ссылка на один справочник, во втором — на другой), результат получит составной тип. Это допустимо, но усложняет дальнейшую обработку: сортировка, группировка и вывод в СКД по составным полям работают медленнее и могут давать неочевидный порядок строк. По возможности приводите поля к одному типу через ВЫРАЗИТЬ(...) КАК.

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

Порядок построения объединения
  1. 1
    Сформулируйте первый запрос и задайте в нём понятные псевдонимы полей через КАК
  2. 2
    Добавьте ОБЪЕДИНИТЬ ВСЕ и второй запрос с тем же числом и порядком колонок
  3. 3
    Проверьте типы полей по позициям; при расхождении приведите их через ВЫРАЗИТЬ
  4. 4
    Выполните запрос в консоли и сверьте количество строк с суммой строк отдельных выборок
  5. 5
    Добавьте итоговое УПОРЯДОЧИТЬ ПО или группировку при необходимости

Когда вместо объединения нужно соединение

Частая ошибка новичков — пытаться объединить таблицы, которые на самом деле нужно соединить. Объединение складывает строки вертикально: было 100 строк продаж и 80 строк закупок — стало 180 строк. Соединение сопоставляет строки по ключу и добавляет колонки: товар и его остаток окажутся в одной строке.

Если задача звучит как «к каждой строке первой таблицы подтянуть данные второй» — это ЛЕВОЕ СОЕДИНЕНИЕ. Если нужны только строки, присутствующие в обеих таблицах, — ВНУТРЕННЕЕ СОЕДИНЕНИЕ. Если требуется полная картина с обеих сторон — ПОЛНОЕ СОЕДИНЕНИЕ с последующей обработкой NULL через ЕСТЬNULL.

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

Маршрут решения

Как выбрать действие

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

Пакетные запросы как альтернатива

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

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

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

bsl
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.Текст =
"ВЫБРАТЬ Товар, Склад, КоличествоОстаток
|ПОМЕСТИТЬ ВТ_Остатки
|ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки
|;
|ВЫБРАТЬ Товар, СУММА(КоличествоОстаток) КАК Остаток
|ИЗ ВТ_Остатки
|СГРУППИРОВАТЬ ПО Товар";
Результат = Запрос.Выполнить().Выгрузить();

Объединение в СКД и отчётах

В системе компоновки данных объединение работает по тем же правилам, но есть нюансы. Объединять источники можно не только в тексте запроса набора данных, но и на уровне самой СКД — через несколько наборов данных типа «Запрос», связанных объединением в схеме. Это позволяет выводить разнородные данные в одну таблицу отчёта без сложного текста запроса.

При объединении в запросе набора данных помните про автозаполнение полей: СКД анализирует структуру первой выборки, поэтому расхождение типов в последующих частях может привести к ошибкам при формировании отчёта. Проверяйте отчёт на данных, где все объединяемые источники непустые — на пустом источнике проблема типов может не проявиться.

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

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

Самая частая ошибка — несовпадение порядка полей. Запрос выполнится без ошибки, если типы случайно совместимы, но данные окажутся перепутаны: в колонке «Количество» окажется сумма. Всегда сверяйте позиции полей визуально и проверяйте результат на контрольном примере с заведомо разными значениями.

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

Третья группа проблем — NULL в полях, которых нет в одной из частей. Когда во втором запросе нет аналога поля, принято подставлять NULL или значение-заглушку (0, пустую строку). Помните, что NULL не равен нулю: итоговые функции его игнорируют, а сравнения с NULL всегда дают ложь. Оборачивайте такие поля в ЕСТЬNULL при дальнейших вычислениях.

Типичные ошибки
01
Разный порядок колонок в объединяемых запросах — данные молча попадают не в те поля
02
ОБЪЕДИНИТЬ вместо ОБЪЕДИНИТЬ ВСЕ на больших выборках — лишняя сортировка и потеря производительности
03
УПОРЯДОЧИТЬ ПО внутри частей объединения — синтаксическая ошибка, сортировка допустима только в конце
04
Сравнение полей с NULL без ЕСТЬNULL — строки теряются из результата
05
Объединение вместо соединения — вместо дополнения строк колонками получается раздутая выборка
Контрольные точки

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

Число строк результата
Норма

Равно сумме строк отдельных выборок (для ВСЕ) или меньше на число дублей

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

Строк заметно больше или меньше без объяснимой причины

Содержимое колонок
Норма

В каждой колонке данные ожидаемого смысла и типа

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

В числовой колонке ссылки, в колонке суммы — количество

Итоги по ключевым показателям
Норма

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

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

Итоги не сходятся — ищите дубли или потерянные строки

Поля-заглушки
Норма

NULL только там, где данных заведомо нет

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

NULL в полях, которые должны быть заполнены всегда

Производительность и ограничения

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

Индексы работают внутри каждой части объединения, но не между частями: сортировка и группировка итогового результата выполняются уже над материализованной выборкой. На больших данных добавляйте отборы как можно раньше — в параметры виртуальных таблиц и условия ГДЕ каждой части.

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

Итог

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

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

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

Можно ли объединить больше двух запросов?

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

Почему после ОБЪЕДИНИТЬ пропали строки?

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

Как объединить запросы с разным числом полей?

Напрямую — никак: число колонок должно совпадать. Недостающие поля дополняют заглушками: NULL, 0, пустой строкой или значением конкретного типа через ВЫРАЗИТЬ. При дальнейшей обработке учитывайте, что NULL не участвует в сравнениях и агрегатах — оборачивайте такие поля в ЕСТЬNULL.

Чем отличается объединение в запросе от объединения наборов данных в СКД?

Объединение в тексте запроса выполняется на уровне СУБД и даёт одну таблицу ещё до передачи в отчёт. Объединение наборов данных в схеме компоновки складывает уже полученные из базы выборки на уровне СКД. Первый вариант обычно быстрее и гибче для отборов, второй удобен, когда источники принципиально разные и требуют собственных настроек связей.

Можно ли использовать объединение во временных таблицах?

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

Как отсортировать результат объединения по колонке, которой нет в первом запросе?

Никак — сортировка возможна только по полям первого запроса. Решение: добавьте нужную колонку в первую часть объединения (в остальных частях подставьте соответствующее значение или NULL), после чего используйте её в УПОРЯДОЧИТЬ ПО. Альтернатива — обернуть объединение во вложенный запрос и сортировать уже его результат.