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

Мы рассмотрим все основные способы объединения: от элементарного ОБЪЕДИНИТЬ до сложных соединений с условиями. Особое внимание уделим разнице между ЛЕВЫМ и ПРАВЫМ соединением — это критично для корректной выборки данных. В конце вас ждут практические примеры с пояснениями и FAQ по частым проблемам.

1. Базовые принципы объединения таблиц в 1С

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

  • 🔹 Вертикальное объединение (ОБЪЕДИНИТЬ) — когда строки добавляются одна под другой (аналог SQL UNION)
  • 🔹 Горизонтальное соединение (СОЕДИНИТЬ, ЛЕВОЕ СОЕДИНЕНИЕ) — когда таблицы объединяются по общим полям (аналог SQL JOIN)
  • 🔹 Вложенные запросы — когда результат одного запроса используется в другом

Основное правило: всегда проверяйте типы данных в объединяемых полях. Например, если в одной таблице поле Дата имеет тип Дата, а в другой — Строка, запрос либо не выполнится, либо вернёт некорректные данные. Для диагностики используйте конструкцию ВЫРАЗИТЬ().

⚠️ Внимание: В платформе 1С ОБЪЕДИНИТЬ по умолчанию удаляет дублирующиеся строки. Чтобы сохранить все записи, используйте ОБЪЕДИНИТЬ ВСЕ.

2. Вертикальное объединение: ОБЪЕДИНИТЬ и ОБЪЕДИНИТЬ ВСЕ

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

Синтаксис:

ВЫБРАТЬ

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

РеализацияТоваровУслуг.Дата

ИЗ

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

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ

ВозвратТоваровОтПокупателя.Ссылка КАК Документ,

ВозвратТоваровОтПокупателя.Дата

ИЗ

Документ.ВозвратТоваровОтПокупателя КАК ВозвратТоваровОтПокупателя

Ключевые моменты:

  • 📌 Количество и типы полей в обоих запросах должны совпадать
  • 📌 Порядок полей важен: первое поле первого запроса соответствует первому полю второго
  • 📌 ОБЪЕДИНИТЬ ВСЕ сохраняет дубли, ОБЪЕДИНИТЬ — удаляет
📊 Какой тип объединения вы используете чаще?
Вертикальное (ОБЪЕДИНИТЬ)
Горизонтальное (СОЕДИНЕНИЕ)
Вложенные запросы
Не использую объединения

3. Горизонтальное соединение: ВНУТРЕННЕЕ, ЛЕВОЕ, ПРАВОЕ

Это основной способ связать таблицы по общим полям. В доступны три типа соединений:

Тип соединения Синтаксис Поведение Аналог в SQL
Внутреннее СОЕДИНИТЬ Только совпадающие строки INNER JOIN
Левое ЛЕВОЕ СОЕДИНЕНИЕ Все строки левой таблицы + совпадающие правой LEFT JOIN
Правое ПРАВОЕ СОЕДИНЕНИЕ Все строки правой таблицы + совпадающие левой RIGHT JOIN
Полное ПОЛНОЕ СОЕДИНЕНИЕ Все строки обеих таблиц FULL JOIN

Пример с ЛЕВЫМ СОЕДИНЕНИЕМ (самый распространённый случай):

ВЫБРАТЬ

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

РегистрНакопления.ОстаткиТоваров.КоличествоОстаток

ИЗ

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

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

ПО Справочник.Номенклатура.Ссылка = РегистрНакопления.ОстаткиТоваров.Номенклатура

💡

Если в результате ЛЕВОГО СОЕДИНЕНИЯ вы получаете NULL в полях правой таблицы, это означает, что для строки из левой таблицы не найдено соответствий в правой. Это нормальное поведение, а не ошибка!

4. Соединение с условиями: WHERE vs ON

Многие разработчики путают, где указывать условия соединения: в секции ПО (аналог ON в SQL) или в ГДЕ (аналог WHERE). Правило простое:

  • 🔧 ПО — условия соединения таблиц (определяют, как таблицы связываются)
  • 🔧 ГДЕ — условия фильтрации результата (отсеивают строки после соединения)

Пример с обоими типами условий:

ВЫБРАТЬ

Документ.ЗаказПокупателя.Номер,

Документ.ЗаказПокупателя.Дата,

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

ИЗ

Документ.ЗаказПокупателя КАК Документ.ЗаказПокупателя

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

ПО Документ.ЗаказПокупателя.Контрагент = Справочник.Контрагенты.Ссылка

ГДЕ

Документ.ЗаказПокупателя.Дата >= &НачалоПериода

И Документ.ЗаказПокупателя.Дата <= &КонецПериода

⚠️ Внимание: Условия в ПО влияют на производительность! Если вы соединяете таблицы по несвязанным полям (например, по дате вместо ссылки), запрос будет выполняться дольше в разы.

5. Практические примеры объединения таблиц

Разберём реальные задачи, с которыми сталкиваются разработчики .

Пример 1: Объединение справочников и документов

Задача: получить список всех номенклатурных позиций с указанием остатков и последней цены продажи.

ВЫБРАТЬ

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

Остатки.КоличествоОстаток КАК Остаток,

MAX(Продажи.Цена) КАК ПоследняяЦена

ИЗ

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

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

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

ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг.Товары КАК Продажи

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

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

Номенклатура.Наименование,

Остатки.КоличествоОстаток

Пример 2: Объединение нескольких регистров

Задача: получить данные о движении товаров из регистров ОстаткиТоваров и ПродажиТоваров.

ВЫБРАТЬ

ДвиженияОстатков.Номенклатура КАК Товар,

ДвиженияОстатков.Количество КАК ИзменениеОстатка,

ДвиженияПродаж.Сумма КАК Выручка

ИЗ

РегистрНакопления.ОстаткиТоваров.Обороты(&НачалоПериода, &КонецПериода) КАК ДвиженияОстатков

ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ПродажиТоваров.Обороты(&НачалоПериода, &КонецПериода) КАК ДвиженияПродаж

ПО ДвиженияОстатков.Номенклатура = ДвиженияПродаж.Номенклатура

Совпадают ли типы объединяемых полей?|Указаны ли все необходимые условия в ПО?|Нет ли лишних ЛЕВЫХ СОЕДИНЕНИЙ, которые можно заменить на ВНУТРЕННИЕ?|Проверены ли права доступа к таблицам?-->

6. Оптимизация запросов с объединением

Объединение таблиц может значительно замедлить выполнение запроса. Вот ключевые правила оптимизации:

  • 🚀 Используйте индексированные поля для соединения (например, Ссылка, а не Наименование)
  • 🚀 Заменяйте ЛЕВОЕ СОЕДИНЕНИЕ на ВНУТРЕННЕЕ, если не нужны строки без соответствий
  • 🚀 Ограничивайте выборку по датам в виртуальных таблицах регистров
  • 🚀 Избегайте соединения более 3-4 таблиц в одном запросе — разбивайте на подзапросы

Пример оптимизированного запроса:

ВЫБРАТЬ

Заказы.Номер,

Заказы.Дата,

Контрагенты.Наименование КАК Покупатель,

Товары.Количество,

Товары.Цена

ИЗ

Документ.ЗаказПокупателя КАК Заказы

ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ЗаказПокупателя.Товары КАК Товары

ПО Заказы.Ссылка = Товары.Ссылка

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

ПО Заказы.Контрагент = Контрагенты.Ссылка

ГДЕ

Заказы.Дата МЕЖДУ &ДатаНачала И &ДатаКонца

И Товары.Номенклатура = &ВыбраннаяНоменклатура

💡

Самая частая ошибка — соединение по неиндексированным полям (например, по наименованию вместо ссылки). Это увеличивает время выполнения запроса в 10-100 раз!

7. Типичные ошибки и их решение

Даже опытные разработчики сталкиваются с проблемами при объединении таблиц. Разберём самые распространённые:

⚠️ Внимание: Если запрос возвращает пустой результат, проверьте:

1) Совпадают ли типы данных в объединяемых полях (используйте ВЫРАЗИТЬ() при необходимости)

2) Есть ли вообще данные в таблицах за указанный период

3) Правильно ли указаны параметры (&Параметр)

Ошибка 1: "Поле не найдено"

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

Ошибка 2: Запрос выполняется слишком долго

Причины и решения:

  • 🐢 Слишком много ЛЕВЫХ СОЕДИНЕНИЙ → замените на ВНУТРЕННИЕ, где возможно
  • 🐢 Соединение по неиндексированным полям → добавьте индексы или используйте ссылки
  • 🐢 Отсутствует фильтрация по датам → ограничьте период в виртуальных таблицах

Ошибка 3: Дублирующиеся строки в результате

Причина: неверное использование ОБЪЕДИНИТЬ вместо ОБЪЕДИНИТЬ ВСЕ или отсутствие ДИСТИНКТ. Решение — добавьте РАЗЛИЧНЫЕ в начало запроса.

8. Альтернативные подходы: вложенные запросы и временные таблицы

Иногда вместо соединения таблиц удобнее использовать:

  • 🔄 Вложенные запросы (подзапросы в секции ГДЕ или ВЫБРАТЬ)
  • 📝 Временные таблицы (для сложных многоэтапных выборок)

Пример с вложенным запросом:

ВЫБРАТЬ

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

Товары.Количество,

(

ВЫБРАТЬ МАКСИМУМ(Цена)

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

ГДЕ Номенклатура = Товары.Номенклатура

) КАК ПоследняяЦена

ИЗ

Документ.ПоступлениеТоваров.Товары КАК Товары

Пример с временной таблицей:

// Создаём временную таблицу с остатками

ВЫБРАТЬ

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

Остатки.КоличествоОстаток КАК Остаток

ПОМЕСТИТЬ втОстатки

ИЗ

РегистрНакопления.ОстаткиТоваров КАК Остатки

// Используем её в основном запросе

ВЫБРАТЬ

Заказы.Номер,

Заказы.Дата,

втОстатки.Остаток

ИЗ

Документ.ЗаказПокупателя КАК Заказы

ЛЕВОЕ СОЕДИНЕНИЕ втОстатки КАК втОстатки

ПО Заказы.Товар = втОстатки.Товар

Когда использовать временные таблицы?

Временные таблицы оправданы, когда:

1. Нужно многократно обращаться к одним и тем же данным в сложном запросе

2. Работаете с большими объёмами данных (более 100 000 строк)

3. Нужно разбить сложный запрос на логические этапы

Но помните: каждая временная таблица увеличивает потребление памяти!

FAQ: Ответы на частые вопросы

Можно ли в 1С сделать FULL OUTER JOIN?

В синтаксисе 1С нет прямого аналога FULL OUTER JOIN, но его можно эмулировать через ОБЪЕДИНИТЬ:

ВЫБРАТЬ ... ЛЕВОЕ СОЕДИНЕНИЕ ...

ОБЪЕДИНИТЬ

ВЫБРАТЬ ... ПРАВОЕ СОЕДИНЕНИЕ ...

Или через три запроса с ЛЕВЫМ, ПРАВЫМ и ВНУТРЕННИМ соединениями.

Почему при ЛЕВОМ СОЕДИНЕНИИ не показываются все строки?

Наиболее вероятные причины:

  1. В условии ГДЕ есть фильтр по полю из правой таблицы (перенесите его в ПО)
  2. Поле соединения в правой таблице содержит NULL (проверьте данные)
  3. Используется ВНУТРЕННЕЕ СОЕДИНЕНИЕ вместо ЛЕВОГО
Как объединить таблицы с разной структурой?

Используйте ОБЪЕДИНИТЬ с явным указанием полей:

ВЫБРАТЬ

NULL КАК Поле1,

Таблица1.ПолеА КАК Поле2

ИЗ Таблица1

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ

Таблица2.ПолеБ КАК Поле1,

NULL КАК Поле2

ИЗ Таблица2

Для несовпадающих полей используйте NULL или функции типа ВЫРАЗИТЬ().

Как ускорить запрос с множеством соединений?

Попробуйте эти методы:

  • Разбейте запрос на несколько с использованием временных таблиц
  • Перенесите фильтры из ГДЕ в условия соединения ПО
  • Используйте ИНДЕКСИРОВАТЬ ПО для больших таблиц
  • Замените ЛЕВОЕ СОЕДИНЕНИЕ на ВНУТРЕННЕЕ, если не нужны пустые строки
Можно ли соединять таблицы из разных баз данных?

Прямого механизма нет, но есть обходные пути:

  1. Использовать распределённые информационные базы (РИБ)
  2. Настроить обмен данными через XML/JSON и загружать данные во временные таблицы
  3. Для 1С:ERP или 1С:УТ использовать сервис интеграции

В простых случаях можно экспортировать данные в Excel и обрабатывать там.