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