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

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

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

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

Задача «соединить два запроса» в 1С встречается в двух разных ситуациях, и путать их нельзя. Первая — объединение результатов двух выборок в одну таблицу «строками друг под другом»: операторы ОБЪЕДИНИТЬ и ОБЪЕДИНИТЬ ВСЕ. Вторая — соединение данных двух таблиц «по колонкам», когда строки одного набора дополняются полями другого по ключу: конструкция СОЕДИНЕНИЕ (ЛЕВОЕ, ПРАВОЕ, ВНУТРЕННЕЕ, ПОЛНОЕ). Выбор зависит от того, что требуется на выходе: общий список записей или расширенный набор полей.

Язык запросов 1С позволяет делать и то, и другое в одном тексте запроса, а также комбинировать подходы через временные таблицы. Ниже разобраны оба механизма с примерами кода, условиями выбора, типичными ошибками и способами проверить результат до того, как запрос попадёт в отчёт или обработку.

Определите, какое соединение вам нужно

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

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

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

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

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

Объединение двух запросов через ОБЪЕДИНИТЬ ВСЕ

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

ВЫБРАТЬ

Поступление.Ссылка КАК Документ,

Поступление.Контрагент КАК Контрагент,

Поступление.СуммаДокумента КАК Сумма

ИЗ

Документ.ПоступлениеТоваровУслуг КАК Поступление

ГДЕ

Поступление.Проведен

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

ВЫБРАТЬ

Реализация.Ссылка,

Реализация.Контрагент,

Реализация.СуммаДокумента

ИЗ

Документ.РеализацияТоваровУслуг КАК Реализация

ГДЕ

Реализация.Проведен

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

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

Соединение двух таблиц по ключу

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

ВЫБРАТЬ

Товары.Ссылка КАК Номенклатура,

Товары.Артикул КАК Артикул,

ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток

ИЗ

Справочник.Номенклатура КАК Товары

ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки

ПО Товары.Ссылка = Остатки.Номенклатура

Обратите внимание на функцию ЕСТЬNULL: если для товара нет записей в регистре остатков, поле остатка вернёт NULL. Без обёртки в ЕСТЬNULL такие значения ломают арифметику, сравнения и группировки дальше по запросу. Это обязательный приём при любом левом соединении, где результат используется в вычислениях.

Виды соединений и когда их применять

Внутреннее соединение (ВНУТРЕННЕЕ СОЕДИНЕНИЕ) возвращает только строки, имеющие пару в обеих таблицах — подходит, когда «осиротевшие» записи не нужны. Правое зеркально левому и на практике используется редко: проще поменять таблицы местами. Полное соединение возвращает все строки обеих сторон с NULL в несопоставленных полях — применяется, например, при сверке двух учётных систем, где важны расхождения в обе стороны.

Сравнение вариантов

ЛЕВОЕ СОЕДИНЕНИЕ

Все строки основной таблицы плюс совпадения. Подходит для «справочник + остатки», «документ + дополнительные сведения»

ВНУТРЕННЕЕ СОЕДИНЕНИЕ

Только пары. Подходит, когда записи без связи заведомо не нужны и должны быть отброшены

ПОЛНОЕ СОЕДИНЕНИЕ

Все строки обеих сторон. Подходит для сверки и поиска расхождений, но тяжелее для СУБД

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

Склейка однотипных выборок по строкам. Не заменяет соединение по ключу

Соединение через временные таблицы

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

ВЫБРАТЬ

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

СУММА(Продажи.Количество) КАК Продано

ПОМЕСТИТЬ ВТ_Продажи

ИЗ

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

СГРУППИРОВАТЬ ПО

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

;

ВЫБРАТЬ

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

СУММА(Закупки.Количество) КАК Закуплено

ПОМЕСТИТЬ ВТ_Закупки

ИЗ

РегистрНакопления.Закупки.Обороты(&Начало, &Конец, , ) КАК Закупки

СГРУППИРОВАТЬ ПО

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

;

ВЫБРАТЬ

ЕСТЬNULL(ВТ_Продажи.Номенклатура, ВТ_Закупки.Номенклатура) КАК Номенклатура,

ЕСТЬNULL(ВТ_Продажи.Продано, 0) КАК Продано,

ЕСТЬNULL(ВТ_Закупки.Закуплено, 0) КАК Закуплено

ИЗ

ВТ_Продажи КАК ВТ_Продажи

ПОЛНОЕ СОЕДИНЕНИЕ ВТ_Закупки КАК ВТ_Закупки

ПО ВТ_Продажи.Номенклатура = ВТ_Закупки.Номенклатура

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

Порядок действий
  1. 1
    Определите тип задачи: склейка строк (ОБЪЕДИНИТЬ) или дополнение полями (СОЕДИНЕНИЕ)
  2. 2
    Проверьте совместимость типов и порядок полей в объединяемых выборках
  3. 3
    При соединении убедитесь, что ключ имеет одинаковый тип в обеих таблицах
  4. 4
    Оберните поля правой таблицы в ЕСТЬNULL при левом или полном соединении
  5. 5
    Соберите запрос в консоли запросов и проверьте на копии базы
  6. 6
    Сравните количество строк и контрольные суммы с исходными выборками

Типичные ошибки и ограничения

Самая частая ошибка — несовпадение порядка полей в объединяемых выборках. Платформа не сопоставляет колонки по именам, поэтому перестановка полей во второй выборке молча смешивает данные. Вторая частая проблема — соединение по полю с разным составом типов: например, ссылка на справочник слева и составное поле (ссылка или строка) справа. Такое соединение может не находить совпадений или работать крайне медленно.

Отдельный класс ошибок — соединение по неуникальному ключу без группировки. Если в правой таблице ключу соответствует несколько строк, левая строка продублируется, и итоговые суммы «поплывут». Перед соединением сгруппируйте правую таблицу по ключу или убедитесь в уникальности. Также помните: условия отбора по полям правой таблицы в секции ГДЕ фактически превращают левое соединение во внутреннее — такие условия нужно переносить в секцию ПО.

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

Проверка результата

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

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

Контрольные точки

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

Число строк при ОБЪЕДИНИТЬ ВСЕ
Норма

Равно сумме строк обеих выборок

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

Меньше суммы — часть данных потеряна из-за отборов или типов

Число строк при левом соединении
Норма

Равно числу строк левой таблицы

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

Больше — ключ правой таблицы неуникален, строки дублируются

Суммы числовых полей
Норма

Совпадают с итогами исходных выборок

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

Завышены — дубли; занижены — потеряны строки

Поля из правой таблицы
Норма

Значения или ожидаемый NULL/ЕСТЬNULL

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

Пустые значения там, где связь точно есть — несовпадение типов ключа

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

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

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

Почему при левом соединении пропадают строки левой таблицы?

Почти всегда причина в условии отбора по полю правой таблицы, размещённом в секции ГДЕ. Для строк без пары это поле равно NULL, условие не выполняется, и строка отбрасывается. Перенесите такое условие в секцию ПО соединения — тогда отбор будет применяться только к сопоставлению.

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

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

Почему соединение не находит совпадений, хотя значения визуально одинаковые?

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

Как соединить два запроса в схеме компоновки данных?

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

Итог

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

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