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