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