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

Многие начинающие специалисты путают этот тип соединения с внутренним, что приводит к потере строк в выборке. Если при внутреннем соединении система отбрасывает строки, для которых нет пары в правой таблице, то левое соединение сохраняет все строки левой таблицы. Для отсутствующих данных из правой таблицы в результат будут подставлены значения NULL (или Неопределено в терминах 1С). Понимание этой механики необходимо для написания корректных и производительных запросов.

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

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

Левое соединение в 1С 8.3 работает по принципу приоритета левой таблицы. Представьте, что у вас есть список сотрудников (левая таблица) и таблица с выданными им пропусками (правая таблица). Ваша задача — вывести список всех сотрудников, указав номер пропуска, если он был выдан. Если использовать внутреннее соединение, то сотрудники без пропусков исчезнут из отчета. Левое соединение решит эту задачу идеально: оно вернет всех сотрудников, а в колонке с номером пропуска у тех, кто его не получил, будет стоять прочерк или пустое значение.

Технически процесс выполнения запроса выглядит следующим образом. Система берет каждую строку из левой таблицы и пытается найтиющую строку в правой таблице по условию соединения (ПО). Если совпадение найдено, строки объединяются в одну результирующую запись. Если совпадения нет, система все равно добавляет строку в результат, но поля, принадлежащие правой таблице, заполняются значением NULL. Это поведение является стандартом для SQL-подобных языков, включая язык запросов .

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

⚠️ Внимание: При использовании левого соединения условие фильтрации, относящееся к полям правой таблицы, нельзя писать в секции ГДЕ, если вы хотите сохранить строки с отсутствующими данными. Фильтрация по полям правой таблицы должна происходить в секции ПО или обрабатываться функцией ЕСТЬNULL в секции ВЫБРАТЬ.

💡

Используйте функцию ЕСТЬNULL(Поле, ЗначениеПоУмолчанию) в списке выбора, чтобы заменить пустые значения NULL на понятные пользователю строки, например,"Нет данных" или 0.

Синтаксис и структура запроса в 1С

Синтаксическая конструкция левого соединения в платформе 1С:Предприятие строго регламентирована. Ключевые слова пишутся на русском языке, что делает код читаемым, но требует внимательности к порядку слов. Базовая структура включает в себя секцию ВЫБРАТЬ, где перечисляются поля, и секцию ИЗ, где описывается соединение таблиц.

Обязательным элементом является условие соединения, которое указывается после ключевого слова ПО. Именно здесь прописывается логика связи между таблицами, обычно через равенство ключевых полей (ссылок). Например, связь между документом и контрагентом осуществляется по полю Контрагент. Ошибка в написании условия ПО часто приводит к декартовому произведению, когда количество строк в результате explodes экспоненциально.

ВЫБРАТЬ

Сотрудники.Ссылка КАК Ссылка,

Сотрудники.ФИО КАК ФИО,

Пропуска.НомерПропуска КАК НомерПропуска

ИЗ

Справочник.Сотрудники КАК Сотрудники

ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Пропуска КАК Пропуска

ПО Сотрудники.Ссылка = Пропуска.Сотрудник

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

💡

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

Отличия от внутреннего и правого соединения

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

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

Ниже приведена таблица, наглядно демонстрирующая различия в поведении типов соединений при наличии и отсутствии связанных записей:

Тип соединения Строки левой таблицы без пары Строки правой таблицы без пары Результат при отсутствии пары
Внутреннее Отбрасываются Отбрасываются Строка не попадает в выборку
Левое Сохраняются Отбрасываются Поля правой таблицы = NULL
Правое Отбрасываются Сохраняются Поля левой таблицы = NULL
Полное Сохраняются Сохраняются Отсутствующие поля = NULL

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

📊 Какой тип соединения вы используете чаще всего?
Внутреннее
Левое
Правое
Полное

Практические примеры использования в отчетах

Рассмотрим реальную задачу из области торговли и склада. Необходимо сформировать отчет по номенклатуре, показав остатки на складах. Проблема в том, что некоторые товары могут еще ни разу не поступать на склад, и записей в регистре накопления ТоварыНаСкладах для них просто не существует. Если использовать внутреннее соединение, эти новые товары не попадут в отчет, и кладовщик не увидит их в списке для планирования закупок.

В этом случае мы берем справочник Номенклатура как левую таблицу и соединяем его с регистром накопления. Запрос вернет весь список товаров. Для тех позиций, где движений не было, колонка с количеством покажет NULL. В коде обработки результата на языке 1С или в СКД (Системе Компоновки Данных) это значение легко заменяется на ноль для корректного отображения.

  • 📦 Анализ продаж: Вывод списка всех менеджеров с суммой их продаж. Менеджеры без продаж не должны исчезать из отчета, чтобы руководитель видел полную картину загрузки персонала.
  • 👥 Кадровый учет: Список всех сотрудников с датами их последних отпусков. Сотрудники, еще не ходившие в отпуск, должны отображаться с пустой датой, а не скрываться из списка штата.
  • 💰 Взаиморасчеты: Вывод всех контрагентов с суммой долга. Контрагенты, с которыми не было операций, должны быть видны со нулевым балансом для проведения сверок.

Еще один важный аспект — работа с периодическими регистрами. При получении среза последних значений (СрезПоследних) часто возникает ситуация, что для какого-то элемента справочника срез не вернул данных (например, цена еще не установлена). Левое соединение со срезом позволяет получить полный список номенклатуры, где у товаров без цены поле будет пустым, что корректно обрабатывается в печатных формах.

Оптимизация при больших объемах

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

Нюансы фильтрации и работа с NULL

Самая распространенная ошибка при работе с левым соединением — неправильная фильтрация результатов. Предположим, вы хотите получить всех сотрудников и их пропуска, но только для отдела"Бухгалтерия". Если вы напишете условие ГДЕ Отдел ="Бухгалтерия", это сработает корректно, так как поле отдела находится в левой таблице. Но что, если вы хотите отфильтровать только тех, у кого есть пропуск определенного типа?

Если вы добавите условие ГДЕ Пропуска.Тип ="Временный", то магия левого соединения исчезнет. Система сначала выполнит соединение (добавив NULL для сотрудников без пропусков), а затем применит фильтр ГДЕ. Строки, где Тип равен NULL, не удовлетворят условию равенства строке"Временный" и будут отброшены. В результате вы получите выборку, идентичную внутреннему соединению.

Чтобы избежать этого, условия фильтрации по полям правой таблицы необходимо переносить в секцию ПО. Это обеспечит то, что фильтрация произойдет до этапа соединения, и отсутствующие значения не будут отсекаться постфактум. Альтернативный вариант — использование конструкции ИЛИ... ЕСТЬ NULL в секции ГДЕ, но перенос в ПО считается более правильным и читаемым подходом.

⚠️ Внимание: Никогда не используйте проверку на неравенство (<>) для полей правой таблицы в секции ГДЕ при левом соединении, если хотите сохранить строки с отсутствующими данными. Это гарантированно превратит запрос во внутреннее соединение.

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

ВЫБРАТЬ

Сотрудники.ФИО,

ЕСТЬNULL(Пропуска.ДатаВыдачи, ДАТАВРЕМЯ(1900, 1, 1)) КАК ДатаВыдачи

ИЗ

Справочник.Сотрудники КАК Сотрудники

ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Пропуска КАК Пропуска

ПО Сотрудники.Ссылка = Пропуска.Сотрудник

Частые ошибки и способы их устранения

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

Чтобы избежать дублирования, необходимо использовать срезы регистров (СрезПоследних, СрезПервых) или агрегатные функции (МАКСИМУМ, МИНИМУМ) с группировкой. Виртуальная таблица среза гарантирует, что для каждого измерения будет возвращена только одна запись, что делает соединение предсказуемым и безопасным для итоговых сумм.

  • 🚫 Отсутствие индексов: Если соединение выполняется по неиндексированным полям, время выполнения запроса может возрасти в разы. Всегда проверяйте конфигурацию базы данных.
  • 🔄 Неверный порядок таблиц: Путаница между левой и правой таблицей приводит к тому, что нужные данные теряются. Визуализируйте схему перед написанием кода.
  • Игнорирование NULL: Попытка выполнить арифметические операции с полями правой таблицы без проверки на NULL может привести к ошибкам выполнения или некорректным расчетам (так как NULL + 5 = NULL).

Также стоит помнить о версиях платформы. Хотя синтаксис левого соединения стабилен в 1С 8.3, поведение оптимизатора запросов может различаться в разных релизах. В очень старых версиях (до 8.3.10) сложные левые соединения с виртуальными таблицами иногда работали некорректно, но в актуальных релизах эти проблемы решены.

☑️ Проверка корректности левого соединения

Выполнено: 0 / 5
В чем главная разница между ЛЕВОЕ СОЕДИНЕНИЕ и ВНУТРЕННЕЕ СОЕДИНЕНИЕ?

Главное отличие заключается в обработке строк левой таблицы, для которых не нашлось соответствия в правой. Внутреннее соединение отбрасывает такие строки, оставляя только полные пары. Левое соединение сохраняет все строки левой таблицы, подставляя NULL в поля правой таблицы там, где совпадений нет.

Как заменить значение NULL на 0 в результате левого соединения?

Для этого в секции ВЫБРАТЬ используйте функцию ЕСТЬNULL. Пример синтаксиса: ЕСТЬNULL(Таблица.Поле, 0) КАК НовоеИмяПоля. Это заменит все пустые значения на ноль непосредственно на уровне запроса.

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

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

Почему мой запрос с левым соединением возвращает меньше строк, чем в левой таблице?

Скорее всего, вы допустили ошибку в фильтрации. Проверьте секцию ГДЕ: если там есть условие, обращающееся к полям правой таблицы (например, ПраваяТаблица.Поле = Значение), оно отсекает строки, где это поле равно NULL. Перенесите такое условие в секцию ПО.