При обмене данными между базами 1С или при интеграции с внешними системами мы регулярно сталкиваемся с задачей сопоставления объектов. Чаще всего это справочник номенклатуры или контрагентов. Рассмотрим типичную ситуацию: есть основная база со справочником номенклатуры и есть регистр сведений, хранящий информацию о сопоставлении кодов нашей номенклатуры с кодами из другой базы. Задача — найти и вывести пользователю те позиции, которые еще не сопоставлены (то есть для них нет записи в регистре, либо код отличается).
Проанализируем ситуацию по шагам и выясним причину, почему обычное соединение таблиц выдает не тот результат, который нам нужен, а также разберем несколько способов решения этой задачи на языке запросов 1С.
Это классический и самый оптимальный способ поиска отсутствующих записей. Разберем по шагам логику его работы.
Когда мы соединяем две таблицы с помощью инструкции ЛЕВОЕ СОЕДИНЕНИЕ, платформа берет все записи из первой (левой) таблицы и пытается найти к ним пару во второй (правой) таблице по указанному условию соединения. Если пара найдена, поля из второй таблицы заполняются соответствующими данными. Но если условие соединения не выполнилось (соответствия нет), в полях второй таблицы образуется специальное значение — NULL (пустота, отсутствие значения).
Остается только отфильтровать результат, чтобы оставить именно эти "пустые" строки. Посмотрим на пример кода:
ВЫБРАТЬ
СпрНоменклатура.Ссылка КАК Номенклатура,
СпрНоменклатура.Код КАК Код
ПОМЕСТИТЬ ВТ_Номенклатура
ИЗ
Справочник.Номенклатура КАК СпрНоменклатура
ГДЕ
СпрНоменклатура.ЭтоГруппа = ЛОЖЬ;
ИНДЕКСИРОВАТЬ ПО
Код;
ВЫБРАТЬ
ВТ_Номенклатура.Номенклатура КАК Номенклатура,
ВТ_Номенклатура.Код КАК КодНоменклатуры
ИЗ
ВТ_Номенклатура КАК ВТ_Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.НоменклатураСопоставление КАК Сопоставление
ПО ВТ_Номенклатура.Код = Сопоставление.КодНоменклатуры
ГДЕ
Сопоставление.КодНоменклатуры ЕСТЬ NULL
В этом запросе мы сначала получаем список номенклатуры во временную таблицу. Затем делаем левое соединение с регистром по коду. Ключевая строка здесь — ГДЕ Сопоставление.КодНоменклатуры ЕСТЬ NULL. Она говорит платформе: "Отбери мне только те строки, которые не смогли присоединиться ко второй таблице". Таким образом мы получаем идеальный список несопоставленной номенклатуры.
Второй вариант решения задачи — использование логического оператора отрицания вхождения в подзапрос. Мы можем выбрать все коды, которые уже есть в регистре сопоставления, и сказать основному запросу исключить их.
ВЫБРАТЬ
СпрНоменклатура.Ссылка КАК Номенклатура
ИЗ
Справочник.Номенклатура КАК СпрНоменклатура
ГДЕ
НЕ СпрНоменклатура.Код В
(ВЫБРАТЬ РАЗЛИЧНЫЕ
Сопоставление.КодНоменклатуры
ИЗ
РегистрСведений.НоменклатураСопоставление КАК Сопоставление)
Данный подход может показаться более читаемым для начинающих разработчиков, однако с точки зрения архитектуры СУБД он часто проигрывает левому соединению. Конструкция НЕ В может приводить к неоптимальным планам выполнения запроса (особенно на PostgreSQL) при больших объемах данных. Кроме того, если в подзапросе случайно окажется значение NULL, результат всей конструкции может стать непредсказуемым. Поэтому первый способ (через левое соединение) считается профессиональным стандартом 1С.
Разберем дополнительные моменты, на которые обязательно нужно обратить внимание при решении задач сопоставления:
ИНДЕКСИРОВАТЬ ПО по тому полю, по которому пойдет дальнейшее соединение. Это критически важно для производительности.000015 (строка) и 15 (число) никогда не соединятся в запросе. То же самое касается префиксов. Если в одной базе код БП-00123, а в другой УТ-00123, прямое соединение не отработает. Необходимо заранее приводить коды к единому строковому виду без префиксов и ведущих нулей.РегистрСведений.НоменклатураСопоставление.СрезПоследних.Если задача сопоставления носит регулярный характер, рекомендуем проанализировать типовой функционал вашей конфигурации (например, 1С:ERP, Комплексная автоматизация или Управление торговлей). Часто создавать "свои" регистры не требуется — в системе уже есть механизмы "Номенклатура партнеров" (или поставщиков), которые предназначены именно для хранения связей между вашей номенклатурой и артикулами/кодами контрагентов. Использование типовых объектов упрощает дальнейшее обслуживание базы и позволяет применять встроенные инструменты помощника сопоставления из подсистемы 1С-ЭДО.