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

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

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

Как соединить три таблицы в запросе 1С: синтаксис ЛЕВОЕ СОЕДИНЕНИЕ, порядок соединений, типичные ошибки, проверка результата и примеры кода для консоли запросов.

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

Язык запросов 1С позволяет соединять любое количество таблиц: после первого соединения просто добавляется второй блок ЛЕВОЕ/ВНУТРЕННЕЕ СОЕДИНЕНИЕ с собственным условием связи. Главное — понимать, какая таблица является основной, по каким полям строятся связи и какой тип соединения выбрать, чтобы не потерять строки и не получить задвоения.

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

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

В языке запросов 1С структура соединения выглядит так: в секции ИЗ указывается основная (левая) таблица, после неё — один или несколько блоков вида «ТИП_СОЕДИНЕНИЯ Источник КАК Псевдоним ПО условие». Каждое следующее соединение присоединяется уже к результату предыдущих, а не только к первой таблице. Поэтому в условии второго соединения можно ссылаться и на поля первой, и на поля второй таблицы.

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

Псевдонимы (КАК) обязательны для читаемости: когда в запросе три таблицы и больше, обращение к полям без псевдонимов быстро приводит к ошибкам «Неоднозначное поле». Принято давать короткие осмысленные псевдонимы: Продажи, Товары, Контрагенты.

Пример запроса: продажи + номенклатура + контрагенты

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

ВЫБРАТЬ

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

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

Продажи.Контрагент КАК Контрагент,

Клиенты.Наименование КАК КлиентНаименование,

Продажи.КоличествоОборот КАК Количество,

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

ИЗ

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

ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Товары

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

ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Клиенты

ПО Продажи.Контрагент = Клиенты.Ссылка

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

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

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

Как выбрать тип соединения для каждой пары таблиц

Выбор типа соединения определяется бизнес-логикой: должна ли строка попасть в результат, если связанной записи нет. Для справочных данных (наименование товара, клиента) почти всегда берут ЛЕВОЕ — отсутствие записи в справочнике не должно скрывать факт продажи. Для жёсткой фильтрации (только товары с заданным свойством) подходит ВНУТРЕННЕЕ.

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

Сравнение типов соединений

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

Все строки основной таблицы плюс найденные пары. Подходит для подтягивания реквизитов из справочников. Риск: NULL в полях правой таблицы.

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

Только строки, где связь нашлась в обеих таблицах. Подходит для фильтрации. Риск: молчаливая потеря строк, если данные неполные.

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

Все строки обеих таблиц. Подходит для сверки двух источников. Риск: NULL с обеих сторон, результат нужно обрабатывать аккуратно.

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

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

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

Временные таблицы как альтернатива сложному соединению

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

Типовая схема пакетного запроса: первая выборка собирает продажи с группировкой по номенклатуре и контрагенту во временную таблицу ВТ_Продажи; вторая готовит срез цен во ВТ_Цены; третья соединяет ВТ_Продажи с ВТ_Цены и справочником номенклатуры. Не забудьте уничтожить временные таблицы (УНИЧТОЖИТЬ), если пакет продолжается дальше, — они занимают память сервера СУБД.

Порядок построения запроса с тремя таблицами
  1. 1
    Определите основную таблицу — ту, чьи строки должны попасть в результат полностью
  2. 2
    Напишите секцию ИЗ с псевдонимом основной таблицы
  3. 3
    Добавьте первое ЛЕВОЕ СОЕДИНЕНИЕ с условием связи по ссылочному полю
  4. 4
    Добавьте второе соединение, проверив, что условие ссылается на корректные поля
  5. 5
    Выполните запрос в консоли и сравните количество строк с количеством строк основной таблицы
  6. 6
    Если строки размножились — сверните присоединяемый источник группировкой во временную таблицу

Типичные ошибки и как их найти

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

Вторая ошибка — потеря строк из-за ВНУТРЕННЕГО соединения там, где нужно ЛЕВОЕ. Например, у части товаров не заполнен поставщик, и ВНУТРЕННЕЕ соединение со справочником поставщиков молча выкидывает эти товары из отчёта. Итоги не сходятся с обороткой, и причина неочевидна.

Третья группа проблем — соединение по неиндексированным полям или по полям разных типов (строка с ссылкой). Такое соединение либо работает очень медленно, либо не находит пар вообще. Всегда соединяйте ссылку со ссылкой, а отборы по строковым представлениям делайте через ГДЕ, а не через ПО.

Типичные ошибки
01
Соединение с физической таблицей регистра сведений вместо СрезПоследних — история размножает строки и завышает итоги
02
ВНУТРЕННЕЕ соединение вместо ЛЕВОГО — строки без пары молча исчезают из отчёта
03
Отсутствие псевдонимов — ошибка «Неоднозначное поле» при одинаковых именах колонок
04
Соединение по полю с составным типом без уточнения — связь находится не для всех строк
05
Условие отбора по правой таблице в секции ГДЕ при левом соединении — фактически превращает его во внутреннее; переносите условие в ПО

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

Любой запрос с соединениями сначала прогоняйте в консоли запросов на реальной базе (копии). Контрольные точки простые: количество строк результата при левых соединениях не должно превышать количество строк основной выборки; итоговые суммы должны совпадать с суммами по основной таблице без соединений; поля присоединённых таблиц могут содержать NULL — это нормально, но NULL не должно быть там, где справочник заполнен обязательно.

Дополнительная проверка — выборочная сверка: возьмите 2–3 строки результата и вручную откройте связанные элементы справочников. Если наименования и значения совпадают, связь построена правильно. Для запросов, которые пойдут в отчёт на СКД, также проверьте, что итоги по ресурсам не задваиваются на уровне группировок.

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

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

Количество строк
Норма

Равно количеству строк основной таблицы (при левых соединениях)

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

Строк стало больше — связь размножает записи

Суммы по ресурсам
Норма

Совпадают с суммами без соединений

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

Суммы выросли — задвоение из-за дочерней таблицы

Поля присоединённых таблиц
Норма

NULL только там, где связанной записи действительно нет

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

NULL повсеместно — условие связи не срабатывает

Условие отбора по полю правой таблицы, записанное в секции ГДЕ, отсекает строки с NULL и тем самым отменяет эффект ЛЕВОГО соединения. Если нужно сохранить строки без пары, перенесите это условие в секцию ПО соответствующего соединения.
ПЗ
Практическое замечание

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

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

Да, ограничения по количеству соединений в языке запросов 1С практически нет — блоки СОЕДИНЕНИЕ добавляются последовательно. Однако с ростом числа соединений падает читаемость и производительность: при 5–7 источниках лучше разбить запрос на пакет с временными таблицами.

Чем соединение отличается от объединения (ОБЪЕДИНИТЬ)?

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

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

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

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

В секции ПО перечислите условия через И: ПО Таб1.Поле1 = Таб2.Поле1 И Таб1.Поле2 = Таб2.Поле2. Это типично для регистров сведений с несколькими измерениями — связь должна учитывать все ключевые поля, иначе строки размножатся.

Что быстрее: соединение или обращение через точку к реквизиту ссылки?

Для одного-двух реквизитов разыменование через точку (Продажи.Номенклатура.Наименование) короче и не требует соединения. Но платформа всё равно выполняет неявное соединение, и при большом числе разыменований явное соединение с выбором нужных полей обычно предпочтительнее и управляемее.

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

В рамках одного запроса — нет, запрос работает только с метаданными текущей базы. Для данных из другой базы сначала загрузите их во временную таблицу через внешний источник, COM/HTTP-обмен или таблицу значений, помещённую в запрос параметром, и соединяйтесь уже с ней.

Итог

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

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