Разработка и Конфигурация · 11 мин
Как сделать левое соединение в запросе 1С
Как написать левое соединение в запросе 1С: синтаксис ЛЕВОЕ СОЕДИНЕНИЕ, примеры кода, работа с NULL, типичные ошибки и способы проверки результата.
Левое соединение — самый частый тип соединения в запросах 1С. Оно возвращает все строки левой таблицы, а из правой подставляет только те записи, для которых выполнилось условие связи. Если пары не нашлось, поля правой таблицы получают значение NULL. Именно поэтому левое соединение применяют, когда нужно показать, например, всех контрагентов независимо от того, были ли у них продажи.
В языке запросов 1С конструкция записывается как ЛЕВОЕ СОЕДИНЕНИЕ ... ПО ... и работает одинаково в консоли запросов, конструкторе запроса и программном коде. Ниже разобран синтаксис, готовые примеры, обработка NULL, типичные ошибки и способы проверить, что запрос вернул именно то, что ожидалось.
Синтаксис левого соединения в языке запросов 1С
Общая форма записи выглядит так: после предложения ИЗ указывается левая таблица с псевдонимом, затем ключевые слова ЛЕВОЕ СОЕДИНЕНИЕ, правая таблица с псевдонимом и после слова ПО — условие связи. Условие чаще всего представляет собой равенство ссылочных полей, но допускает и составные выражения через И, а также неравенства.
ВЫБРАТЬ
Номенклатура.Ссылка КАК Товар,
Остатки.КоличествоОстаток КАК Остаток
ИЗ
Справочник.Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки
ПО Номенклатура.Ссылка = Остатки.Номенклатура
В этом примере левая таблица — справочник «Номенклатура», правая — виртуальная таблица остатков. В результат попадут все товары из справочника, в том числе те, по которым остатков нет: у них поле Остаток будет равно NULL. Псевдонимы (КАК Номенклатура, КАК Остатки) технически необязательны, но без них запрос быстро становится нечитаемым, особенно при нескольких соединениях.
Как собрать запрос в конструкторе без ручного кода
Если синтаксис пока не запомнился, запрос удобно собрать в конструкторе. Откройте конструктор запроса (в модуле — через контекстное меню «Конструктор запроса»), добавьте обе таблицы на закладку «Таблицы и поля», затем перетащите поле связи из одной таблицы на соответствующее поле другой — конструктор сам создаст соединение.
По умолчанию конструктор 1С создает именно левое соединение, что видно по значку связи в списке связей таблиц. Тип соединения можно сменить: выделите связь и в свойствах выберите «Левое», «Внутреннее», «Правое» или «Полное». После нажатия «ОК» конструктор сформирует готовый текст запроса, который останется только вставить в код.
- 1Откройте конструктор запроса и добавьте левую и правую таблицы
- 2Перетащите поле связи из одной таблицы на поле другой
- 3Проверьте тип связи — должен быть «Левое соединение»
- 4Выберите нужные поля из обеих таблиц
- 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.
Левое соединение против других типов соединений
В языке запросов 1С доступны четыре типа соединения. Внутреннее возвращает только строки, нашедшие пару в обеих таблицах; правое — зеркало левого; полное возвращает все строки обеих таблиц. На практике левое и внутреннее покрывают почти все задачи, а правое обычно переписывают как левое, поменяв таблицы местами — так запрос читается единообразно.
Сравнение типов соединений
Все строки левой таблицы плюс совпадения справа. Подходит для «все элементы + данные, если есть». Требует обработки NULL.
Только строки с парой в обеих таблицах. Подходит, когда нужны именно пересечения, например товары с ненулевыми остатками.
Все строки обеих таблиц. Используется редко, например для сверки двух источников. NULL возможны с обеих сторон.
Выбор простой: если потеря строк левой таблицы недопустима (нужно показать всех клиентов, все товары, все документы) — берите левое соединение. Если строки без пары бессмысленны для задачи — внутреннее. Когда сомневаетесь, начните с левого и посмотрите на результат: лишние строки с NULL легче заметить, чем молча пропавшие записи.
Как выбрать тип соединения
Как проверить, что соединение сработало правильно
Быстрый способ проверки — консоль запросов в режиме предприятия. Выполните запрос и сравните количество строк результата с количеством записей левой таблицы (с учетом её отборов). Если строк больше — где-то дублирование по неуникальному ключу правой таблицы. Если меньше — проверьте, не отсекает ли условие ГДЕ строки с NULL.
Второй контроль — итоговые суммы. Посчитайте сумму по числовому полю до соединения (отдельным запросом по правой таблице с теми же отборами) и после. Значения должны совпадать; расхождение почти всегда означает дублирование строк. Для ссылочных полей полезно вывести представление или код, чтобы визуально убедиться, что связь сработала по нужному полю.
Как проверить результат
Равно числу строк левой таблицы с её отборами
Строк больше — дублирование из-за неуникального ключа правой таблицы
NULL только там, где пары заведомо нет, числа заменены через ЕСТЬNULL
NULL в строках, где данные точно должны быть — неверное условие связи
Совпадают с суммой по правой таблице отдельно
Суммы завышены — строки задублировались при соединении
Частые вопросы о левом соединении в 1С
Чем левое соединение отличается от внутреннего на практике?
Внутреннее соединение отбрасывает строки, не нашедшие пары во второй таблице, а левое сохраняет все записи левой таблицы, подставляя NULL вместо отсутствующих данных. Если нужен отчет «все контрагенты и их продажи», берите левое; если «только контрагенты с продажами» — внутреннее.
Почему после левого соединения суммы в отчете увеличились?
Почти наверняка правая таблица содержит несколько строк на одно значение ключа связи, и строки левой таблицы задублировались. Сгруппируйте правую таблицу во временной таблице по полю связи с суммированием показателей, а затем соединяйтесь уже с ней.
Как заменить NULL на ноль или пустую ссылку?
Используйте функцию ЕСТЬNULL: ЕСТЬNULL(Поле, 0) для чисел, ЕСТЬNULL(Поле, ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)) для ссылок. Для строк подставьте пустую строку. Функция работает и в полях выборки, и в условиях.
Можно ли соединять больше двух таблиц?
Да, соединения перечисляются последовательно: левая таблица, затем несколько блоков ЛЕВОЕ СОЕДИНЕНИЕ подряд, каждый со своим условием ПО. Условие каждого соединения может ссылаться на любые таблицы, объявленные раньше в запросе.
Как найти записи, которым не нашлось пары?
Добавьте после левого соединения условие ГДЕ ПолеПравойТаблицы ЕСТЬ NULL. В результат попадут только те строки левой таблицы, для которых совпадения не нашлось — удобно для поиска товаров без остатков или контрагентов без документов.
Влияет ли порядок таблиц на результат левого соединения?
Да, принципиально: левой считается таблица, указанная до ключевых слов ЛЕВОЕ СОЕДИНЕНИЕ, и именно её строки сохраняются все. Если поменять таблицы местами, смысл запроса изменится — поэтому всегда осознанно выбирайте, какая таблица «главная» в вашей задаче.
Что важно запомнить
Левое соединение пишется как ЛЕВОЕ СОЕДИНЕНИЕ с условием ПО и сохраняет все строки левой таблицы. Обрабатывайте NULL через ЕСТЬNULL, не выносите условия по правой таблице в ГДЕ, задавайте отборы в параметрах виртуальных таблиц и проверяйте результат по количеству строк и итоговым суммам.