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

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

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

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

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

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

Соединение и объединение: в чём разница

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

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

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

СОЕДИНЕНИЕ

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

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

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

ОБЪЕДИНИТЬ (без ВСЕ)

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

Левое соединение: подтянуть данные к каждой строке

Левое соединение — самый используемый вид в прикладных запросах 1С. Результат включает все строки левой таблицы, а из правой подставляются только найденные соответствия; если соответствия нет, поля правой таблицы будут NULL. Это безопасный вариант: вы не потеряете товары без цены или сотрудников без начислений.

ВЫБРАТЬ

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

Товары.Наименование,

Цены.Цена КАК Цена

ИЗ

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

ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних КАК Цены

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

Обратите внимание на псевдонимы (КАК Товары, КАК Цены) — без них запрос со многими таблицами быстро становится нечитаемым. Условие связи пишется после ПО и может содержать несколько условий через И, например связь по номенклатуре и типу цен одновременно.

Почему левое, а не внутреннее

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

bsl
ЕСТЬNULL(Цены.Цена, 0) КАК Цена

Правое и полное соединение: когда они нужны

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

Полное соединение (ПОЛНОЕ СОЕДИНЕНИЕ) выводит все строки обеих таблиц, а где пары нет — подставляет NULL с одной из сторон. Оно полезно для сверки двух источников: например, сравнить остатки по данным бухгалтерского и складского учёта и найти расхождения в обе стороны. Строки, где одна из колонок NULL, — это и есть несовпадения.

Объединение выборок через ОБЪЕДИНИТЬ ВСЕ

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

ВЫБРАТЬ

Поступления.Номенклатура КАК Товар,

Поступления.Количество КАК Количество,

"Поступление" КАК ВидОперации

ИЗ

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

ГДЕ

Поступления.Ссылка.Проведен

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

ВЫБРАТЬ

Списания.Номенклатура,

-Списания.Количество,

"Списание"

ИЗ

Документ.СписаниеТоваров.Товары КАК Списания

ГДЕ

Списания.Ссылка.Проведен

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

Поле-константа вроде "Поступление" / "Списание" в примере выше — стандартный приём: он позволяет в итоговой таблице различать источник каждой строки и при необходимости группировать или фильтровать по нему.

Соединение с виртуальными таблицами регистров

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

ВЫБРАТЬ

Товары.Ссылка КАК Товар,

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

ИЗ

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

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

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

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

Типичные ошибки и как их избежать

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

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

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

Как проверить результат объединения

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

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

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

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

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

Равно числу строк левой таблицы (или меньше за счёт отбора)

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

Строк стало больше — ключ связи неуникален, данные задваиваются

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

Заполнены там, где связь есть; NULL обработан через ЕСТЬNULL

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

NULL в суммовых полях ломает итоги и группировки

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

Равны сумме итогов отдельных подзапросов

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

Итог меньше — часть строк потеряна из-за несовпадения типов или порядка полей

Что выбрать в конкретной ситуации

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

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

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

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

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

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

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

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

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

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

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

Как соединить таблицы по нескольким полям?

Перечислите условия после ПО через логическое И: ПО Товары.Ссылка = Цены.Номенклатура И Цены.ТипЦен = &ТипЦен. Все условия должны выполняться одновременно, иначе соответствие не будет найдено.

Можно ли объединить больше двух таблиц?

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

Что делать, если в объединяемых подзапросах разные типы поля?

Приведите значения к общему типу функцией ВЫРАЗИТЬ, например ВЫРАЗИТЬ(Поле КАК Строка(100)), или подставьте вместо несовместимого значения NULL либо константу нужного типа. Тип итогового поля определяется первым подзапросом.

Как избежать задвоения строк при соединении с табличной частью?

Сначала сверните табличную часть вложенным запросом с группировкой по ключу связи (например, суммируйте количество по номенклатуре), а затем соединяйте уже свёрнутый результат. Тогда каждому ключу будет соответствовать ровно одна строка.