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

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

Как сопоставить две таблицы в 1С: рабочие способы и проверка результата

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

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

Главный принцип: сначала определите ключ сопоставления — поле или набор полей, по которым строки двух таблиц считаются «одинаковыми». Все ошибки при сопоставлении сводятся к неверно выбранному ключу: дубли по ключу, различия в типах данных, лишние пробелы, разные представления одной сущности (например, ИНН с пробелами и без).

Ниже разобраны основные сценарии: соединение таблиц в запросе, сопоставление таблиц значений программно, работа с типовой загрузкой данных и проверка результата. Каждый способ имеет свои ограничения и подходит для своего объёма данных.

Определите ключ сопоставления и подготовьте данные

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

Перед сопоставлением проверьте типы и форматы. Частые источники проблем: число в одной таблице и строка в другой, артикул с неразрывными пробелами из Excel, дата как строка «01.02.2026». Приведите значения к одному виду заранее: СокрЛП() для строк, Число() или ВЫРАЗИТЬ(... КАК ЧИСЛО(15,2)) в запросе, удаление неразрывных пробелов через СтрЗаменить(Значение, Символ(160), "").

Уникальность ключаНет дублей по ключу

Сгруппируйте таблицу по ключу и посчитайте количество — оно должно равняться 1 для каждого значения

Типы полей ключаТипы совпадают

Строка со строкой, число с числом, ссылка со ссылкой; иначе соединение не сработает или даст неполный результат

Объём таблицДо десятков тысяч строк

Для больших объёмов используйте запрос с индексированными полями, а не вложенные циклы

Источник данныхБаза, ТЗ или файл

От источника зависит инструмент: запрос, программный обход или механизм загрузки

Сопоставление данных в базе через запрос

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

// Сверка остатков двух регистров: ищем расхождения

ВЫБРАТЬ

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

ЕСТЬNULL(ОстаткиУчет.КоличествоОстаток, 0) КАК КоличествоУчет,

ЕСТЬNULL(ОстаткиСклад.КоличествоОстаток, 0) КАК КоличествоСклад

ИЗ

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

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

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

ГДЕ

ЕСТЬNULL(ОстаткиУчет.КоличествоОстаток, 0) <> ЕСТЬNULL(ОстаткиСклад.КоличествоОстаток, 0)

Полное соединение удобно для сверки: оно покажет строки, которые есть только в одной из таблиц, и строки с разными значениями. Функция ЕСТЬNULL обязательна — иначе сравнение с NULL не сработает, и расхождение будет пропущено.

Для поиска «есть в первой, нет во второй» используйте левое соединение с условием ГДЕ Таблица2.Ключ ЕСТЬ NULL. Это стандартный приём для поиска отсутствующих документов, незаполненных карточек и т.п.

Сопоставление двух таблиц значений программно

Когда данные уже загружены в таблицы значений (например, одна получена из файла, вторая — выгрузкой запроса), есть два подхода. Первый — поместить обе ТЗ во временные таблицы запроса через параметр и дальше соединить обычным SQL-подобным запросом. Это быстро и позволяет использовать все виды соединений.

Запрос = Новый Запрос;

Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;

Запрос.Текст =

"ВЫБРАТЬ Т.Ключ, Т.Значение ПОМЕСТИТЬ Таб1 ИЗ &ТЗ1 КАК Т;

|ВЫБРАТЬ Т.Ключ, Т.Значение ПОМЕСТИТЬ Таб2 ИЗ &ТЗ2 КАК Т;

|ВЫБРАТЬ Таб1.Ключ, Таб1.Значение, Таб2.Значение

|ИЗ Таб1 ЛЕВОЕ СОЕДИНЕНИЕ Таб2 ПО Таб1.Ключ = Таб2.Ключ";

Запрос.УстановитьПараметр("ТЗ1", Таблица1);

Запрос.УстановитьПараметр("ТЗ2", Таблица2);

Результат = Запрос.Выполнить().Выгрузить();

Второй подход — соответствие как индекс. Пройдите вторую таблицу один раз и сложите строки в Соответствие по ключу, затем при обходе первой таблицы ищите пару через Соответствие[Ключ]. Это работает за линейное время и подходит для десятков тысяч строк, тогда как вложенный цикл с Найти() по неиндексированной таблице на больших объёмах будет работать неприемлемо долго.

Если всё же ищете методом Найти(), добавьте индекс: ТЗ.Индексы.Добавить("Ключ"). Без индекса каждый поиск перебирает таблицу целиком.

bsl
// Индекс через соответствие
Индекс = Новый Соответствие;
Для Каждого Стр Из Таблица2 Цикл
    Индекс.Вставить(СокрЛП(Стр.Артикул), Стр);
КонецЦикла;
Для Каждого Стр1 Из Таблица1 Цикл
    Стр2 = Индекс[СокрЛП(Стр1.Артикул)];
    Если Стр2 <> Неопределено Тогда
        Стр1.Сопоставлено = Истина;
    КонецЕсли;
КонецЦикла;

Сопоставление при загрузке данных из файла

При загрузке из Excel или CSV нужно связать строки файла с элементами справочников. В типовых конфигурациях есть обработка «Загрузка данных из файла» (в разделах справочников — кнопка «Загрузить»): она автоматически предлагает сопоставление колонок файла реквизитам справочника и ищет существующие элементы по выбранным полям.

Если пишете свою загрузку, порядок такой: прочитайте файл в таблицу значений, нормализуйте ключевые поля (обрезка пробелов, приведение регистра, удаление лишних символов), затем одним запросом найдите все существующие элементы по списку ключей и постройте соответствие «ключ → ссылка». После этого один проход по таблице файла заполнит ссылки без обращений к базе в цикле.

Поиск по наименованию — частая ошибка. Наименования редактируются, дублируются и отличаются пробелами. Ищите по коду, артикулу, ИНН, штрихкоду или GUID, а наименование используйте только как вспомогательный признак для ручного разбора несопоставленных строк.

Как выбрать способ сопоставления

Выбор зависит от расположения данных и объёма. Таблица ниже помогает быстро сориентироваться.

СитуацияИнструментОграничение
Обе таблицы в базеЗапрос с соединениемНужны индексированные поля ключа
Две таблицы значений в памятиВременные таблицы запроса или соответствиеТЗ целиком в памяти — при очень больших объёмах дробите
Файл + справочникТиповая загрузка или запрос по списку ключейКлюч должен быть надёжным (код, артикул, ИНН)
Нечёткое совпадение (похожие строки)Программный перебор с нормализациейМедленно, требует ручной проверки
Маршрут решения

Как выбрать действие

Данные в регистрах или справочниках базыПишите запрос с ЛЕВЫМ, ПОЛНЫМ или ВНУТРЕННИМ соединением по индексированному ключу
Обе таблицы уже в памяти как ТЗ и строк до нескольких тысячИспользуйте соответствие-индекс и один проход по первой таблице
Нужны сложные условия соединения по ТЗПоместите ТЗ во временные таблицы запроса и соедините запросом
Ключ неоднозначен, есть похожие, но не равные значенияСделайте таблицу кандидов и выведите её пользователю на ручное сопоставление

Проверка результата сопоставления

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

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

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

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

Количество строк результата
Норма

При внутреннем соединении не больше меньшей из таблиц

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

Строк больше, чем в любой из исходных таблиц — дубли по ключу

Суммы по числовым полям
Норма

Итоги по сгруппированному результату совпадают с исходными

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

Суммы выросли после соединения — размножение строк

Несопоставленные строки
Норма

Список пуст или все причины известны

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

Много NULL там, где пары должны быть — проблема с типами или форматом ключа

Сравнение с NULL
Норма

Используется ЕСТЬNULL при сравнении значений

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

Расхождения с NULL пропускаются условием <>

Типичные ошибки и ограничения

Самая частая ошибка — соединение по наименованию или другому редактируемому полю. Вторая по частоте — забытый ЕСТЬNULL при сравнении: условие Таб1.Количество <> Таб2.Количество не сработает, если одна из сторон NULL, и расхождение будет потеряно. Третья — вложенные циклы с поиском без индекса на больших таблицах: обработка зависает на десятки минут.

Ограничения: запрос не умеет «нечёткое» сравнение (похожие строки), а соответствие требует точного совпадения ключа с учётом типа. Если задача — сопоставить «похожие» наименования контрагентов, готового типового решения нет: нормализуйте строки (убрать ООО, кавычки, регистр) и сравнивайте программно с выводом кандидатов на ручную проверку.

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

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

Как найти строки, которые есть в первой таблице, но отсутствуют во второй?

Используйте левое соединение с условием на NULL: ЛЕВОЕ СОЕДИНЕНИЕ ... ГДЕ Таблица2.Ключ ЕСТЬ NULL. В результат попадут только строки первой таблицы, для которых пара не найдена. Программно то же самое делается проверкой Если Соответствие[Ключ] = Неопределено Тогда.

Почему соединение не находит пары, хотя значения визуально совпадают?

Почти всегда причина в невидимых различиях: неразрывные пробелы (символ 160), лишние пробелы в конце, разный регистр букв, разные типы данных (строка «123» и число 123) или разная длина строкового поля. Нормализуйте оба ключа одинаковым способом и сравните снова.

Что быстрее: запрос или программный перебор таблиц значений?

Для данных в базе — всегда запрос: он выполняется на сервере СУБД с использованием индексов. Для таблиц значений в памяти перебор с соответствием-индексом сопоставим по скорости с запросом через временные таблицы, но запрос удобнее при сложных условиях и группировках.

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

В запросе перечислите все условия через И: ПО Таб1.Номенклатура = Таб2.Номенклатура И Таб1.Склад = Таб2.Склад. При программном сопоставлении сформируйте составной ключ-строку, например Ключ = Строка(Номенклатура.УникальныйИдентификатор()) + "|" + Строка(Склад.УникальныйИдентификатор()), и используйте его в соответствии.

Можно ли сопоставить таблицы без программирования?

Частично. В типовых конфигурациях есть «Загрузка данных из файла» со встроенным сопоставлением, а для сверки данных базы подойдут универсальные отчёты и консоль запросов (входит в стандартные инструменты разработчика или поставляется отдельно). Сложные сценарии с нечёткими ключами без кода не решаются.

Итог

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

Сначала выберите надёжный уникальный ключ и приведите типы и форматы в обеих таблицах. Данные в базе соединяйте запросом, таблицы значений — через временные таблицы или соответствие-индекс. Всегда проверяйте количество сопоставленных и несопоставленных строк, используйте ЕСТЬNULL при сравнениях и тестируйте загрузку с записью на копии базы.