Как в запросе 1С найти несопоставленные записи (отсутствующие во второй таблице)?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При обмене данными между базами 1С или при интеграции с внешними системами мы регулярно сталкиваемся с задачей сопоставления объектов. Чаще всего это справочник номенклатуры или контрагентов. Рассмотрим типичную ситуацию: есть основная база со справочником номенклатуры и есть регистр сведений, хранящий информацию о сопоставлении кодов нашей номенклатуры с кодами из другой базы. Задача — найти и вывести пользователю те позиции, которые еще не сопоставлены (то есть для них нет записи в регистре, либо код отличается).

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

Способ 1: Использование левого соединения и условия ЕСТЬ NULL (IS NULL)

Это классический и самый оптимальный способ поиска отсутствующих записей. Разберем по шагам логику его работы.

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

Остается только отфильтровать результат, чтобы оставить именно эти "пустые" строки. Посмотрим на пример кода:


ВЫБРАТЬ
    СпрНоменклатура.Ссылка КАК Номенклатура,
    СпрНоменклатура.Код КАК Код
ПОМЕСТИТЬ ВТ_Номенклатура
ИЗ
    Справочник.Номенклатура КАК СпрНоменклатура
ГДЕ
    СпрНоменклатура.ЭтоГруппа = ЛОЖЬ;

ИНДЕКСИРОВАТЬ ПО
    Код;

ВЫБРАТЬ
    ВТ_Номенклатура.Номенклатура КАК Номенклатура,
    ВТ_Номенклатура.Код КАК КодНоменклатуры
ИЗ
    ВТ_Номенклатура КАК ВТ_Номенклатура
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.НоменклатураСопоставление КАК Сопоставление
        ПО ВТ_Номенклатура.Код = Сопоставление.КодНоменклатуры
ГДЕ
    Сопоставление.КодНоменклатуры ЕСТЬ NULL

В этом запросе мы сначала получаем список номенклатуры во временную таблицу. Затем делаем левое соединение с регистром по коду. Ключевая строка здесь — ГДЕ Сопоставление.КодНоменклатуры ЕСТЬ NULL. Она говорит платформе: "Отбери мне только те строки, которые не смогли присоединиться ко второй таблице". Таким образом мы получаем идеальный список несопоставленной номенклатуры.

Способ 2: Использование конструкции НЕ В (NOT IN)

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


ВЫБРАТЬ
    СпрНоменклатура.Ссылка КАК Номенклатура
ИЗ
    Справочник.Номенклатура КАК СпрНоменклатура
ГДЕ
    НЕ СпрНоменклатура.Код В
        (ВЫБРАТЬ РАЗЛИЧНЫЕ
            Сопоставление.КодНоменклатуры
        ИЗ
            РегистрСведений.НоменклатураСопоставление КАК Сопоставление)

Данный подход может показаться более читаемым для начинающих разработчиков, однако с точки зрения архитектуры СУБД он часто проигрывает левому соединению. Конструкция НЕ В может приводить к неоптимальным планам выполнения запроса (особенно на PostgreSQL) при больших объемах данных. Кроме того, если в подзапросе случайно окажется значение NULL, результат всей конструкции может стать непредсказуемым. Поэтому первый способ (через левое соединение) считается профессиональным стандартом 1С.

Важные технические нюансы и оптимизация

Разберем дополнительные моменты, на которые обязательно нужно обратить внимание при решении задач сопоставления:

  1. Индексация временных таблиц: Если мы предварительно собираем номенклатуру во временную таблицу (ВТ), как показано в первом примере, обязательно используйте конструкцию ИНДЕКСИРОВАТЬ ПО по тому полю, по которому пойдет дальнейшее соединение. Это критически важно для производительности.
  2. Типы данных и форматы кодов: Самая частая причина "несопоставления" — разница форматов. Код 000015 (строка) и 15 (число) никогда не соединятся в запросе. То же самое касается префиксов. Если в одной базе код БП-00123, а в другой УТ-00123, прямое соединение не отработает. Необходимо заранее приводить коды к единому строковому виду без префиксов и ведущих нулей.
  3. Работа с регистрами сведений: Если регистр сопоставления является периодическим (имеет измерение "Период"), то прямое обращение к физической таблице регистра будет ошибкой. Мы рискуем получить дубли или неактуальные данные. В таком случае нужно использовать виртуальную таблицу РегистрСведений.НоменклатураСопоставление.СрезПоследних.

Типовые альтернативы

Если задача сопоставления носит регулярный характер, рекомендуем проанализировать типовой функционал вашей конфигурации (например, 1С:ERP, Комплексная автоматизация или Управление торговлей). Часто создавать "свои" регистры не требуется — в системе уже есть механизмы "Номенклатура партнеров" (или поставщиков), которые предназначены именно для хранения связей между вашей номенклатурой и артикулами/кодами контрагентов. Использование типовых объектов упрощает дальнейшее обслуживание базы и позволяет применять встроенные инструменты помощника сопоставления из подсистемы 1С-ЭДО.

← На главную