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

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

Как работают соединения в запросах 1С

Как работают соединения в запросах 1С: ЛЕВОЕ, ПРАВОЕ, ВНУТРЕННЕЕ, ПОЛНОЕ. Синтаксис, примеры кода, типичные ошибки и способы проверки результата запроса.

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

Ошибки в соединениях — одна из самых частых причин «плавающих» дефектов: запрос вроде бы работает, но теряет строки, дублирует данные или возвращает NULL там, где пользователь ожидает конкретное значение. Понимание логики каждого типа соединения и умения проверять результат помогают находить такие проблемы до выкладки в рабочую базу.

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

Как устроено соединение: таблицы, псевдонимы и условие ПО

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

Типичный фрагмент выглядит так:

ВЫБРАТЬ

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

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

ИЗ

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

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

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

Условие ПО может содержать несколько выражений, объединённых И. Чем точнее условие, тем меньше риск декартова размножения строк. Условия неравенства (например, сравнение периодов) допустимы, но резко снижают производительность, потому что платформа не может использовать индексы обычным образом.

Важно понимать порядок обработки: платформа сначала формирует пары строк по условию ПО, и только потом применяются отборы из секции ГДЕ (кроме случаев, когда отбор относится к параметрам виртуальной таблицы). Поэтому фильтрация в ГДЕ может «сломать» левое соединение — об этом подробнее ниже.

ВНУТРЕННЕЕ соединение: только совпавшие строки

ВНУТРЕННЕЕ соединение возвращает только те пары строк, для которых условие ПО выполняется. Если в одной из таблиц нет соответствия, строка полностью исключается из результата. Это самый «строгий» и обычно самый быстрый тип соединения.

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

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

ЛЕВОЕ соединение: сохранить все строки основной таблицы

ЛЕВОЕ соединение возвращает все строки левой таблицы. Если в правой таблице соответствие не найдено, поля правой таблицы заполняются значением NULL. Это самый распространённый тип соединения в учётных запросах: справочник товаров слева, остатки или цены справа — и в результат попадают все товары, включая те, по которым данных нет.

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

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

ПОЛНОЕ соединение и поиск несвязанных записей

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

Классическая задача — найти записи, присутствующие только в одной из таблиц. Для этого к полному соединению добавляют условие вида:

ГДЕ

Таблица1.Ключ ЕСТЬ NULL

ИЛИ Таблица2.Ключ ЕСТЬ NULL

Тот же результат можно получить через ЛЕВОЕ соединение с проверкой «ПравоеПоле ЕСТЬ NULL» — это стандартный приём поиска товаров без цен, контрагентов без договоров и подобных «осиротевших» записей. Такой вариант часто читается проще и не требует полного соединения.

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

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

Выбор определяется одним вопросом: строки какой таблицы обязаны попасть в результат независимо от наличия связи. Если только совпадения — ВНУТРЕННЕЕ. Если вся левая таблица — ЛЕВОЕ. Если обе целиком — ПОЛНОЕ.

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

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

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

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

Если соединяются виртуальные таблицы регистров (СрезПоследних, Остатки, Обороты), передавайте отборы через параметры виртуальной таблицы, а не через ГДЕ. Это уменьшает объём вычисляемых данных до соединения и заметно ускоряет запрос.

Множественные соединения и временные таблицы

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

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

Порядок построения сложного запроса
  1. 1
    Определите основную таблицу — ту, чьи строки должны сохраниться полностью
  2. 2
    Выберите тип соединения для каждой присоединяемой таблицы по правилу «какие строки нельзя потерять»
  3. 3
    Запишите условия связи в ПО, отборы по правой таблице — туда же или в параметры виртуальной таблицы
  4. 4
    Проверьте запрос в консоли на реальных данных: количество строк, доля NULL, отсутствие дублей
  5. 5
    При росте сложности вынесите промежуточные выборки во временные таблицы и проверьте каждую отдельно

При соединении следите за кратностью связи. Если к одной строке левой таблицы подходит несколько строк правой, строка продублируется — итоги по суммовым полям завысятся. Если детализация правой таблицы не нужна, предварительно сверните её (СГРУППИРОВАТЬ ПО с СУММА или МАКСИМУМ) во временной таблице или вложенном запросе.

Типичные ошибки и проверка результата

Большинство проблем с соединениями укладывается в несколько повторяющихся сценариев. Знание их признаков позволяет диагностировать дефект за минуты, а не часы.

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

Проверять результат удобно по контрольным точкам: количество строк, поведение NULL и сходимость итогов. Консоль запросов позволяет выполнить запрос на реальных данных и сразу увидеть отклонения.

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

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

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

Соответствует ожиданиям для выбранного типа соединения (не меньше левой таблицы при ЛЕВОМ)

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

Строк меньше, чем в основной таблице, хотя соединение левое — вероятно, лишний отбор в ГДЕ

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

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

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

Массовые NULL при заведомо заполненных данных — ошибка в условии ПО

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

Итоги сходятся с данными исходных таблиц

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

Суммы кратно завышены — дублирование строк из-за связи «один ко многим»

Время выполнения
Норма

Запрос выполняется за приемлемое для интерактивной работы время

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

Резкое замедление при добавлении соединения — проверьте параметры виртуальных таблиц и индексируемость полей связи

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

Итог

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

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

Частые вопросы о соединениях в запросах 1С

Чем ЛЕВОЕ соединение отличается от ВНУТРЕННЕГО на практике?

ВНУТРЕННЕЕ возвращает только строки, нашедшие пару в обеих таблицах, а ЛЕВОЕ сохраняет все строки левой таблицы, подставляя NULL в поля правой при отсутствии связи. Практический критерий: если отсутствие связанных данных не должно скрывать объект из выборки — нужно ЛЕВОЕ.

Почему после добавления условия в ГДЕ пропали строки из левого соединения?

Условие по полю правой таблицы в секции ГДЕ применяется после соединения и отбрасывает строки, где это поле равно NULL. Перенесите условие в часть ПО соединения или дополните его проверкой «ИЛИ Поле ЕСТЬ NULL».

Как найти записи, для которых нет связи в другой таблице?

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

Почему суммы в отчёте удваиваются после соединения?

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

Можно ли соединять таблицу саму с собой?

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

Что быстрее — соединение или вложенный запрос?

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