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