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

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

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

Использование оператора UNION для объединения множеств

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

Использование UNION автоматически удаляет дубликаты строк из итогового результата. Если вам критично сохранить все записи, даже идентичные, следует применять модификатор UNION ALL. Это может существенно ускорить выполнение запроса, так как системе не придется тратить ресурсы на сортировку и сравнение строк для поиска повторов.

Рассмотрим синтаксис на примере объединения списка контрагентов из справочника и списка партнеров из временной таблицы:


ВЫБРАТЬ

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

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

ИЗ

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

ОБЪЕДИНИТЬ

ВЫБРАТЬ

ВременнаяТаблица.Ссылка,

ВременнаяТаблица.Наименование

ИЗ

ВременнаяТаблица

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

⚠️ Внимание: При объединении запросов следите за порядком полей. Если во втором запросе вы перепутаете порядок колонок, данные попадут в неверные поля результата, что приведет к логическим ошибкам в отчете, которые трудно отследить.

💡

Используйте UNION ALL вместо обычного UNION, если вы уверены, что в выборках нет дублей. Это ускорит выполнение запроса, так как исключит этап удаления повторяющихся строк.

Внутреннее соединение (INNER JOIN) по ключевым полям

Когда необходимо получить данные только для тех записей, которые существуют одновременно в двух таблицах, применяется конструкция INNER JOIN. Это классическое соединение, которое фильтрует результат, оставляя лишь пересечение множеств. Например, если нужно вывести список документов только по тем контрагентам, у которых заполнен ИНН.

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

Пример запроса с внутренним соединением документов и справочника номенклатуры:


ВЫБРАТЬ

Документ.РеализацияТоваровУслуг.Ссылка КАК Документ,

Документ.РеализацияТоваровУслуг.Номер,

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

ИЗ

Документ.РеализацияТоваровУслуг КАК Реализация

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

ПО Реализация.Ссылка = Остатки.Регистратор

ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура

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

В данном примере мы гарантируем, что в выборку попадут только те документы, по которым есть движения в регистре накопления, и только та номенклатура, которая существует в справочнике. Это мощный инструмент для фильтрации "мусорных" данных на уровне базы.

☑️ Проверка корректности JOIN

Выполнено: 0 / 4

Левое внешнее соединение (LEFT JOIN) для сохранения всех записей

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

Этот тип соединения незаменим при формировании аналитических отчетов, где важно видеть полную картину, даже если по каким-то позициям данные отсутствуют. Например, список всех товаров на складе, где для некоторых товаров еще не установлены цены в прайс-листе.

Максимальный объем данных сохраняется из левой таблицы (той, что идет до слова СОЕДИНЕНИЕ). Правая таблица служит источником дополнительных атрибутов. Если условие соединения не выполняется, строка из левой таблицы все равно попадает в результат.

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

Тип соединения Записи из левой таблицы Записи из правой таблицы Результат при отсутствии связи
Внутреннее (INNER) Только совпадающие Только совпадающие Строка исключается
Левое (LEFT) Все Только совпадающие NULL в полях правой таблицы
Правое (RIGHT) Только совпадающие Все NULL в полях левой таблицы
Полное (FULL) Все Все NULL в отсутствующих полях

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

Особенность NULL в 1С

В языке запросов 1С пустая ссылка ведет себя как NULL. При сравнении с использованием оператора = пустая ссылка не равна NULL. Для проверки на отсутствие значения используйте конструкцию "ЕСТЬ NULL".

Вложенные запросы и временные таблицы

Иногда соединить два запроса напрямую в одном операторе ВЫБРАТЬ невозможно из-за сложности логики или ограничений синтаксиса. В таких случаях на помощь приходят вложенные запросы. Вы можете выполнить первый запрос, поместить его результат во временную таблицу, а затем присоединить к ней второй запрос.

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

Пример использования вложенного запроса для фильтрации перед соединением:


ВЫБРАТЬ

Основной.Ссылка,

Основной.Сумма

ИЗ

(ВЫБРАТЬ

Документ.ЗаказКлиента.Ссылка,

СУММА(Документ.ЗаказКлиента.Сумма) КАК Сумма

ИЗ

Документ.ЗаказКлиента

ГДЕ

Документ.ЗаказКлиента.Проведен = ИСТИНА

СГРУППИРОВАТЬ ПО

Документ.ЗаказКлиента.Ссылка) КАК Основной

ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Клиенты КАК Клиенты

ПО Основной.Ссылка.Владелец = Клиенты.Ссылка

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

📊 Какой метод соединения вы используете чаще всего?
UNION
INNER JOIN
LEFT JOIN
Вложенные запросы

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

При соединении двух запросов, особенно с использованием UNION или соединений "многие-ко-многим", высок риск получения дублирующихся строк. Это может исказить итоги отчетов и замедлить работу системы. Анализ плана выполнения запроса помогает выявить узкие места.

Дубликаты часто возникают, когда одна запись из левой таблицы соединяется с несколькими записями из правой. В результате строка из левой таблицы размножается. Чтобы избежать этого, можно использовать оператор РАЗЛИЧНЫЕ (аналог DISTINCT) или группировать результаты.

Рекомендации по оптимизации:

  • 🚀 Всегда проверяйте наличие индексов по полям, участвующим в условии ПО. Без индексов соединение больших таблиц может занять минуты.
  • 📉 Избегайте функций в условии соединения (например, ЛЕВЫЙ(Поле, 3)). Это запрещает использование индексов и заставляет базу перебирать все строки.
  • 🔍 Используйте временные таблицы с индексами, если промежуточный результат велик. Это ускорит последующие соединения.

⚠️ Внимание: Чрезмерное использование вложенных запросов без необходимости может усложнить чтение кода и затруднить оптимизацию СУБД. Старайтесь писать максимально плоские запросы там, где это возможно.

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

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

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

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

💡

Главный принцип оптимизации: фильтруйте данные как можно раньше. Используйте условия в виртуальных таблицах и вложенных запросах, чтобы уменьшить объем данных перед основным соединением.

Частые ошибки при объединении данных

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

Еще одна проблема — потеря контекста при использовании UNION. Поскольку это операция над множествами, связи между строками разных частей запроса теряются. Если вам нужно сохранить связь, используйте JOIN или добавляйте общий идентификатор в выбираемые поля.

Список распространенных ошибок:

  • ❌ Разное количество полей в частях UNION.
  • ❌ Отсутствие псевдонимов у таблиц в сложных соединениях, что приводит к конфликту имен полей.
  • ❌ Использование полей из правой таблицы в условии WHERE при LEFT JOIN, что превращает его в INNER JOIN.

Для предотвращения ошибок всегда тестируйте каждую часть запроса отдельно перед их объединением. Консоль запросов в конфигураторе 1С — ваш лучший помощник в этом процессе. Она позволяет пошагово проверять синтаксис и структуру результатов.

В чем разница между UNION и UNION ALL?

UNION удаляет дубликаты строк из итогового результата, выполняя дополнительную сортировку и сравнение. UNION ALL просто склеивает результаты двух запросов, сохраняя все строки, включая повторяющиеся. UNION ALL работает быстрее.

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

Да, вы можете соединять неограниченное количество запросов, цепочкой применяя операторы UNION или JOIN. Главное — соблюдать синтаксическую правильность и соответствие типов данных на каждом этапе.

Как соединить запросы, если поля называются по-разному?

Используйте псевдонимы (КАК) в секции ВЫБРАТЬ, чтобы привести имена полей к общему виду. Для соединения по разным полям используйте условие ПО с явным указанием соответствия: Таблица1.Поле1 = Таблица2.Поле2.

Что делать, если запрос выполняется слишком долго?

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

Можно ли использовать UNION в подзапросе?

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