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