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

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

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

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

Левое соединение — самый частый тип соединения в запросах 1С. Оно возвращает все строки левой таблицы, а из правой подставляет только те записи, для которых выполнилось условие связи. Если пары не нашлось, поля правой таблицы получают значение NULL. Именно поэтому левое соединение применяют, когда нужно показать, например, всех контрагентов независимо от того, были ли у них продажи.

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

Синтаксис левого соединения в языке запросов 1С

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

ВЫБРАТЬ

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

Остатки.КоличествоОстаток КАК Остаток

ИЗ

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

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

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

В этом примере левая таблица — справочник «Номенклатура», правая — виртуальная таблица остатков. В результат попадут все товары из справочника, в том числе те, по которым остатков нет: у них поле Остаток будет равно NULL. Псевдонимы (КАК Номенклатура, КАК Остатки) технически необязательны, но без них запрос быстро становится нечитаемым, особенно при нескольких соединениях.

Как собрать запрос в конструкторе без ручного кода

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

По умолчанию конструктор 1С создает именно левое соединение, что видно по значку связи в списке связей таблиц. Тип соединения можно сменить: выделите связь и в свойствах выберите «Левое», «Внутреннее», «Правое» или «Полное». После нажатия «ОК» конструктор сформирует готовый текст запроса, который останется только вставить в код.

Порядок действий в конструкторе
  1. 1
    Откройте конструктор запроса и добавьте левую и правую таблицы
  2. 2
    Перетащите поле связи из одной таблицы на поле другой
  3. 3
    Проверьте тип связи — должен быть «Левое соединение»
  4. 4
    Выберите нужные поля из обеих таблиц
  5. 5
    Нажмите ОК и проверьте сформированный текст запроса

Работа с NULL в полях правой таблицы

Главная особенность левого соединения — появление NULL там, где парной записи нет. NULL в 1С не равен нулю и пустой строке: сравнение Остатки.КоличествоОстаток = 0 для NULL-значения вернет ложь, а арифметика с NULL даст NULL. Если этого не учесть, отчет покажет пустые цифры, а условия отбора «потеряют» строки.

Стандартное решение — функция ЕСТЬNULL, которая подставляет значение по умолчанию: ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток. Для ссылочных полей вместо 0 подставляют пустую ссылку: ЕСТЬNULL(Продажи.Менеджер, ЗНАЧЕНИЕ(Справочник.Пользователи.ПустаяСсылка)). Для проверки на NULL в условиях используется конструкция ГДЕ Поле ЕСТЬ NULL или НЕ Поле ЕСТЬ NULL.

ВЫБРАТЬ

Контрагенты.Ссылка КАК Контрагент,

ЕСТЬNULL(Продажи.СуммаОборот, 0) КАК СуммаПродаж

ИЗ

Справочник.Контрагенты КАК Контрагенты

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

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

ГДЕ

Продажи.Контрагент ЕСТЬ NULL

Условие ГДЕ Продажи.Контрагент ЕСТЬ NULL превращает левое соединение в инструмент поиска «осиротевших» записей: запрос выше вернет контрагентов, по которым вообще не было продаж. Это частый прием для поиска справочных элементов без движений, документов без строк и тому подобных задач.

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

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

ВЫБРАТЬ

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

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

ИЗ

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

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

&Период, Склад = &Склад) КАК Остатки

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

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

Типичные ошибки при левом соединении

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

Вторая ошибка — условия по правой таблице в секции ГДЕ, о которых сказано выше: они отсекают NULL-строки и незаметно превращают левое соединение во внутреннее. Третья — соединение по полям разных типов (например, строка с кодом справочника): СУБД не сможет использовать индекс, и запрос на больших таблицах начнет выполняться минутами. Четвертая — забытый ЕСТЬNULL, из-за которого в СКД и при обходе выборки приходится отдельно обрабатывать NULL.

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

Левое соединение против других типов соединений

В языке запросов 1С доступны четыре типа соединения. Внутреннее возвращает только строки, нашедшие пару в обеих таблицах; правое — зеркало левого; полное возвращает все строки обеих таблиц. На практике левое и внутреннее покрывают почти все задачи, а правое обычно переписывают как левое, поменяв таблицы местами — так запрос читается единообразно.

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

Левое соединение

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

Внутреннее соединение

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

Полное соединение

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

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

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

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

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

Как проверить, что соединение сработало правильно

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

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

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

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

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

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

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

Строк больше — дублирование из-за неуникального ключа правой таблицы

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

NULL только там, где пары заведомо нет, числа заменены через ЕСТЬNULL

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

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

Суммы по числовым полям
Норма

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

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

Суммы завышены — строки задублировались при соединении

Частые вопросы о левом соединении в 1С

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

Внутреннее соединение отбрасывает строки, не нашедшие пары во второй таблице, а левое сохраняет все записи левой таблицы, подставляя NULL вместо отсутствующих данных. Если нужен отчет «все контрагенты и их продажи», берите левое; если «только контрагенты с продажами» — внутреннее.

Почему после левого соединения суммы в отчете увеличились?

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

Как заменить NULL на ноль или пустую ссылку?

Используйте функцию ЕСТЬNULL: ЕСТЬNULL(Поле, 0) для чисел, ЕСТЬNULL(Поле, ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)) для ссылок. Для строк подставьте пустую строку. Функция работает и в полях выборки, и в условиях.

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

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

Как найти записи, которым не нашлось пары?

Добавьте после левого соединения условие ГДЕ ПолеПравойТаблицы ЕСТЬ NULL. В результат попадут только те строки левой таблицы, для которых совпадения не нашлось — удобно для поиска товаров без остатков или контрагентов без документов.

Влияет ли порядок таблиц на результат левого соединения?

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

Итог

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

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