Разработка и Конфигурация · 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);
Результат = Запрос.Выполнить().Выгрузить();
Второй подход — соответствие как индекс. Пройдите вторую таблицу один раз и сложите строки в Соответствие по ключу, затем при обходе первой таблицы ищите пару через Соответствие[Ключ]. Это работает за линейное время и подходит для десятков тысяч строк, тогда как вложенный цикл с Найти() по неиндексированной таблице на больших объёмах будет работать неприемлемо долго.
Если всё же ищете методом Найти(), добавьте индекс: ТЗ.Индексы.Добавить("Ключ"). Без индекса каждый поиск перебирает таблицу целиком.
// Индекс через соответствие
Индекс = Новый Соответствие;
Для Каждого Стр Из Таблица2 Цикл
Индекс.Вставить(СокрЛП(Стр.Артикул), Стр);
КонецЦикла;
Для Каждого Стр1 Из Таблица1 Цикл
Стр2 = Индекс[СокрЛП(Стр1.Артикул)];
Если Стр2 <> Неопределено Тогда
Стр1.Сопоставлено = Истина;
КонецЕсли;
КонецЦикла;Сопоставление при загрузке данных из файла
При загрузке из Excel или CSV нужно связать строки файла с элементами справочников. В типовых конфигурациях есть обработка «Загрузка данных из файла» (в разделах справочников — кнопка «Загрузить»): она автоматически предлагает сопоставление колонок файла реквизитам справочника и ищет существующие элементы по выбранным полям.
Если пишете свою загрузку, порядок такой: прочитайте файл в таблицу значений, нормализуйте ключевые поля (обрезка пробелов, приведение регистра, удаление лишних символов), затем одним запросом найдите все существующие элементы по списку ключей и постройте соответствие «ключ → ссылка». После этого один проход по таблице файла заполнит ссылки без обращений к базе в цикле.
Поиск по наименованию — частая ошибка. Наименования редактируются, дублируются и отличаются пробелами. Ищите по коду, артикулу, ИНН, штрихкоду или GUID, а наименование используйте только как вспомогательный признак для ручного разбора несопоставленных строк.
Как выбрать способ сопоставления
Выбор зависит от расположения данных и объёма. Таблица ниже помогает быстро сориентироваться.
| Ситуация | Инструмент | Ограничение |
|---|---|---|
| Обе таблицы в базе | Запрос с соединением | Нужны индексированные поля ключа |
| Две таблицы значений в памяти | Временные таблицы запроса или соответствие | ТЗ целиком в памяти — при очень больших объёмах дробите |
| Файл + справочник | Типовая загрузка или запрос по списку ключей | Ключ должен быть надёжным (код, артикул, ИНН) |
| Нечёткое совпадение (похожие строки) | Программный перебор с нормализацией | Медленно, требует ручной проверки |
Как выбрать действие
Проверка результата сопоставления
После сопоставления обязательно посчитайте три числа: сколько строк первой таблицы нашло пару, сколько не нашло и сколько строк второй таблицы осталось без пары. Сумма должна сходиться с исходными количествами. Если сопоставленных строк больше, чем строк в меньшей таблице, — у вас дубли по ключу и размножение строк.
Полезный приём — вывести несопоставленные строки отдельным списком и разобрать причины: опечатка в ключе, отсутствующий элемент справочника, архивная запись. Автоматически «дожимать» такие строки нельзя — это источник ошибок в учёте.
Как проверить результат
При внутреннем соединении не больше меньшей из таблиц
Строк больше, чем в любой из исходных таблиц — дубли по ключу
Итоги по сгруппированному результату совпадают с исходными
Суммы выросли после соединения — размножение строк
Список пуст или все причины известны
Много NULL там, где пары должны быть — проблема с типами или форматом ключа
Используется ЕСТЬNULL при сравнении значений
Расхождения с NULL пропускаются условием <>
Типичные ошибки и ограничения
Самая частая ошибка — соединение по наименованию или другому редактируемому полю. Вторая по частоте — забытый ЕСТЬNULL при сравнении: условие Таб1.Количество <> Таб2.Количество не сработает, если одна из сторон NULL, и расхождение будет потеряно. Третья — вложенные циклы с поиском без индекса на больших таблицах: обработка зависает на десятки минут.
Ограничения: запрос не умеет «нечёткое» сравнение (похожие строки), а соответствие требует точного совпадения ключа с учётом типа. Если задача — сопоставить «похожие» наименования контрагентов, готового типового решения нет: нормализуйте строки (убрать ООО, кавычки, регистр) и сравнивайте программно с выводом кандидатов на ручную проверку.
Частые вопросы
Как найти строки, которые есть в первой таблице, но отсутствуют во второй?
Используйте левое соединение с условием на NULL: ЛЕВОЕ СОЕДИНЕНИЕ ... ГДЕ Таблица2.Ключ ЕСТЬ NULL. В результат попадут только строки первой таблицы, для которых пара не найдена. Программно то же самое делается проверкой Если Соответствие[Ключ] = Неопределено Тогда.
Почему соединение не находит пары, хотя значения визуально совпадают?
Почти всегда причина в невидимых различиях: неразрывные пробелы (символ 160), лишние пробелы в конце, разный регистр букв, разные типы данных (строка «123» и число 123) или разная длина строкового поля. Нормализуйте оба ключа одинаковым способом и сравните снова.
Что быстрее: запрос или программный перебор таблиц значений?
Для данных в базе — всегда запрос: он выполняется на сервере СУБД с использованием индексов. Для таблиц значений в памяти перебор с соответствием-индексом сопоставим по скорости с запросом через временные таблицы, но запрос удобнее при сложных условиях и группировках.
Как сопоставить таблицы по нескольким полям одновременно?
В запросе перечислите все условия через И: ПО Таб1.Номенклатура = Таб2.Номенклатура И Таб1.Склад = Таб2.Склад. При программном сопоставлении сформируйте составной ключ-строку, например Ключ = Строка(Номенклатура.УникальныйИдентификатор()) + "|" + Строка(Склад.УникальныйИдентификатор()), и используйте его в соответствии.
Можно ли сопоставить таблицы без программирования?
Частично. В типовых конфигурациях есть «Загрузка данных из файла» со встроенным сопоставлением, а для сверки данных базы подойдут универсальные отчёты и консоль запросов (входит в стандартные инструменты разработчика или поставляется отдельно). Сложные сценарии с нечёткими ключами без кода не решаются.
Что важно запомнить
Сначала выберите надёжный уникальный ключ и приведите типы и форматы в обеих таблицах. Данные в базе соединяйте запросом, таблицы значений — через временные таблицы или соответствие-индекс. Всегда проверяйте количество сопоставленных и несопоставленных строк, используйте ЕСТЬNULL при сравнениях и тестируйте загрузку с записью на копии базы.