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

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

Как объединить таблицы в 1С: запросы и программные способы

Как объединить таблицы в 1С: оператор ОБЪЕДИНИТЬ ВСЕ в запросах, соединение таблиц, слияние таблиц значений в коде, типичные ошибки и проверка результата.

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

В языке запросов 1С объединение выполняется оператором ОБЪЕДИНИТЬ (по умолчанию с удалением дублей) и ОБЪЕДИНИТЬ ВСЕ (с сохранением всех строк). Для горизонтального «склеивания» по ключу применяется СОЕДИНЕНИЕ. В коде на встроенном языке таблицы значений объединяют перебором строк или через запрос с помещением таблиц во временные таблицы.

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

Что значит «объединить таблицы»: вертикально или горизонтально

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

Горизонтальное объединение (соединение) — это когда к строкам одной таблицы по общему ключу подставляются колонки другой: растёт число колонок, а число строк определяется типом соединения. Пример — к таблице товаров добавить цены из регистра сведений по совпадению номенклатуры.

Смешение этих задач — самая частая причина ошибок. Если таблицы имеют разный набор полей, ОБЪЕДИНИТЬ не подойдёт: нужно либо соединение, либо приведение структур к общему виду с пустыми значениями или NULL в недостающих колонках.

Объединение таблиц в запросе через ОБЪЕДИНИТЬ ВСЕ

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

Пример — объединить отгрузки и возвраты в одну таблицу движений:

ВЫБРАТЬ

Реализация.Номенклатура КАК Номенклатура,

Реализация.Количество КАК Количество,

"Отгрузка" КАК ТипДвижения

ИЗ

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

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

ВЫБРАТЬ

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

-Возврат.Количество,

"Возврат"

ИЗ

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

Используйте ОБЪЕДИНИТЬ ВСЕ всегда, когда дубли либо невозможны по смыслу, либо нужны. Вариант без ВСЕ заставляет платформу дополнительно сворачивать результат, что замедляет запрос на больших объёмах. Чистый ОБЪЕДИНИТЬ оправдан только когда дубликаты строк действительно нужно устранить.

Если в одной из таблиц нет нужного поля, подставьте константу или NULL, чтобы выровнять структуру: ВЫБРАТЬ Товары.Номенклатура, NULL КАК Серия .... Несовпадение числа полей — ошибка времени выполнения запроса, поэтому проверяйте каждую часть отдельно в консоли запросов перед сборкой.

Порядок объединения в запросе
  1. 1
    Напишите и отладьте каждую выборку отдельно в консоли запросов
  2. 2
    Выровняйте количество и типы полей, недостающие замените на NULL или константы
  3. 3
    Соедините части оператором ОБЪЕДИНИТЬ ВСЕ
  4. 4
    Добавьте итоги, группировку или упорядочивание к итоговой выборке
  5. 5
    Проверьте количество строк: оно должно равняться сумме строк частей

Соединение таблиц по ключу: ЛЕВОЕ, ВНУТРЕННЕЕ и другие

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

ВЫБРАТЬ

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

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

ЕСТЬNULL(Цены.Цена, 0) КАК Цена

ИЗ

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

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

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

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

Объединение таблиц значений в коде

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

ИтоговаяТаблица = Таблица1.Скопировать();

Для Каждого СтрокаТЗ Из Таблица2 Цикл

НоваяСтрока = ИтоговаяТаблица.Добавить();

ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТЗ);

КонецЦикла;

Метод ЗаполнитьЗначенияСвойств переносит только те свойства, имена которых совпадают с колонками приёмника — это защищает от ошибок при разной структуре, но молча «теряет» несовпадающие колонки. Если состав колонок различается, сначала добавьте недостающие колонки в итоговую таблицу через Колонки.Добавить("Имя", ОписаниеТипа).

Для больших таблиц (десятки тысяч строк) быстрее работает вариант через запрос: обе таблицы помещаются в менеджер временных таблиц, а затем объединяются оператором ОБЪЕДИНИТЬ ВСЕ. Это также удобно, когда после слияния нужно сразу сгруппировать или соединить результат с данными базы.

bsl
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.Текст =
"ВЫБРАТЬ * ПОМЕСТИТЬ Т1 ИЗ &Таблица1 КАК Таблица1
";
Запрос.УстановитьПараметр("Таблица1", Таблица1);
Запрос.Выполнить();

Какой способ выбрать в разных ситуациях

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

Как выбрать способ

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

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

Для отчётов на СКД объединение делается прямо в наборе данных типа «Объединение» — платформа сама формирует конструкцию ОБЪЕДИНИТЬ ВСЕ по набору запросов. Это предпочтительный путь для отчётов: он сохраняет настройки группировок и отборов пользователя.

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

После объединения всегда сверяйте контрольные числа: количество строк и суммы по ключевым числовым полям до и после. Для ОБЪЕДИНИТЬ ВСЕ число строк результата должно равняться сумме строк частей; для ЛЕВОГО СОЕДИНЕНИЯ — числу строк левой таблицы (если нет дублей ключа справа).

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

Как проверить результат

Количество строк после ОБЪЕДИНИТЬ ВСЕ
Норма

Равно сумме строк всех частей

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

Строк меньше — части свернулись, проверьте, не использован ли ОБЪЕДИНИТЬ без ВСЕ

Суммы после ЛЕВОГО СОЕДИНЕНИЯ
Норма

Суммы по левой таблице не изменились

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

Суммы выросли — дубли ключа в правой таблице

Значения в колонках из правой таблицы
Норма

NULL только там, где пары действительно нет

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

Повсеместные NULL — ошибка в условии соединения или несовпадение типов ключа

Типичные ошибки
01
ОБЪЕДИНИТЬ без ВСЕ там, где строки разных частей совпадают — часть данных молча исчезает из результата
02
Разное количество или порядок полей в частях объединения — ошибка выполнения запроса
03
Соединение по ключу с дублями в правой таблице — задвоение строк и завышенные итоги
04
Сравнение ключей разных типов (например, строка и ссылка) в условии соединения — соединение не срабатывает
05
Потеря колонок при слиянии таблиц значений через ЗаполнитьЗначенияСвойств из-за разных имён колонок

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

Итог

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

Вертикальное слияние в запросе — ОБЪЕДИНИТЬ ВСЕ с одинаковым набором полей, горизонтальное — СОЕДИНЕНИЕ по ключу с контролем дублей. Таблицы значений в коде сливаются добавлением строк либо через временные таблицы. Результат всегда проверяйте по количеству строк и контрольным суммам.

Частые вопросы

Чем ОБЪЕДИНИТЬ отличается от ОБЪЕДИНИТЬ ВСЕ?

ОБЪЕДИНИТЬ удаляет полностью совпадающие строки из результата, ОБЪЕДИНИТЬ ВСЕ сохраняет все строки. Вариант без ВСЕ требует дополнительной обработки и работает медленнее, поэтому применяйте его только когда дедупликация действительно нужна.

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

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

Как объединить таблицы с разным набором колонок?

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

Почему после ЛЕВОГО СОЕДИНЕНИЯ строк стало больше?

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

Как объединить таблицы в отчёте на СКД?

В схеме компоновки данных добавьте набор данных типа «Объединение» и включите в него несколько наборов-запросов. СКД сама построит объединение по совпадающим именам полей; следите, чтобы состав и типы полей наборов совпадали.

Что быстрее: слияние таблиц значений в цикле или через запрос?

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