Как найти эталонного контрагента среди дублей с помощью запроса 1С?

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

В процессе эксплуатации информационных систем, особенно при интеграции нескольких баз (CRM, Бухгалтерия, Торговля), неизбежно возникает проблема дублирования данных. Одной из самых сложных задач является не просто поиск дублей по наименованию, а определение так называемой «золотой записи» или эталона. Рассмотрим, как реализовать механизм поиска эталона и отделения его от дублей с помощью одного пакетного запроса, опираясь на сложные критерии: присутствие объекта в разных базах и полноту заполнения его реквизитов.

Постановка задачи и критерии эталонности

Проанализируем ситуацию: в самописном справочнике Контрагенты имеются записи, пришедшие из разных источников. У каждой записи есть реквизиты-идентификаторы (УИД) для каждой из баз: CRM, БП (Бухгалтерия), Торговля. Также введен показатель Вес — это число заполненных значимых реквизитов в карточке.

Разберем алгоритм выбора эталона, который нам необходимо внедрить в запрос:

  1. Связь с Бухгалтерией: Если среди дублей с одинаковым наименованием есть несколько записей из CRM, но только одна из них имеет сопоставленный УИД в Бухгалтерии (БП), именно она считается эталонной.
  2. Максимальный охват баз: Если несколько записей имеют связь с БП, эталоном становится та, которая встречается в максимальном количестве информационных систем (сумма заполненных идентификаторов источников).
  3. Весовой коэффициент: Если количество баз одинаково, эталоном признается запись с максимальным значением реквизита Вес (наибольшая заполненность данных).

Решение через пакетный запрос и временные таблицы

Поскольку стандартный язык запросов 1С (до версии 8.3.20) не поддерживал оконные функции в полной мере, наиболее надежным способом решения является использование временных таблиц. Рассмотрим пошагово, как построить такой запрос.

Шаг 1: Сбор всех кандидатов и расчет их характеристик

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


ВЫБРАТЬ
    Контрагенты.Ссылка КАК Ссылка,
    Контрагенты.НаименованиеПолное КАК НаименованиеПолное,
    Контрагенты.Вес КАК Вес,
    (ВЫБОР КОГДА Контрагенты.УИД_CRM <> "" ТОГДА 1 ИНАЧЕ 0 КОНЕЦ + 
     ВЫБОР КОГДА Контрагенты.УИД_БП <> "" ТОГДА 1 ИНАЧЕ 0 КОНЕЦ + 
     ВЫБОР КОГДА Контрагенты.УИД_Торговля <> "" ТОГДА 1 ИНАЧЕ 0 КОНЕЦ) КАК КоличествоБаз,
    ВЫБОР КОГДА Контрагенты.УИД_БП <> "" ТОГДА 1 ИНАЧЕ 0 КОНЕЦ КАК НаличиеБП
ПОМЕСТИТЬ ВТ_ДанныеКонтрагентов
ИЗ
    Справочник.Контрагенты КАК Контрагенты
ГДЕ
    НЕ Контрагенты.ЭтоГруппа
    И Контрагенты.НаименованиеПолное В (
        ВЫБРАТЬ
            К.НаименованиеПолное
        ИЗ
            Справочник.Контрагенты КАК К
        СГРУППИРОВАТЬ ПО
            К.НаименованиеПолное
        ИМЕЮЩИЕ
            КОЛИЧЕСТВО(К.Ссылка) > 1
    )
;

Шаг 2: Определение максимальных показателей в группе

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


ВЫБРАТЬ
    ВТ.НаименованиеПолное КАК НаименованиеПолное,
    МАКСИМУМ(ВТ.НаличиеБП) КАК МаксБП,
    МАКСИМУМ(ВТ.КоличествоБаз) КАК МаксБаз,
    МАКСИМУМ(ВТ.Вес) КАК МаксВес
ПОМЕСТИТЬ ВТ_МаксимальныеПоказатели
ИЗ
    ВТ_ДанныеКонтрагентов КАК ВТ
СГРУППИРОВАТЬ ПО
    ВТ.НаименованиеПолное
;

Шаг 3: Итоговый выбор эталона и дублей

Теперь объединим данные. Выясним, какая запись соответствует всем критериям лидерства. Мы используем ВНУТРЕННЕЕ СОЕДИНЕНИЕ, чтобы сопоставить текущие записи с максимальными значениями по группе. Важный момент: если даже после всех проверок остаются две абсолютно идентичные по весу и базам записи, мы выберем одну по внутреннему идентификатору Ссылка (используя МАКСИМУМ(Ссылка)), чтобы избежать появления двух эталонов для одного имени.


ВЫБРАТЬ
    ВТ.НаименованиеПолное,
    ВТ.Ссылка КАК Эталон
ПОМЕСТИТЬ ВТ_Эталоны
ИЗ
    ВТ_ДанныеКонтрагентов КАК ВТ
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_МаксимальныеПоказатели КАК Макс
    ПО ВТ.НаименованиеПолное = Макс.НаименованиеПолное
    И ВТ.НаличиеБП = Макс.МаксБП
    И ВТ.КоличествоБаз = Макс.МаксБаз
    И ВТ.Вес = Макс.МаксВес
;

Использование оконных функций (для платформы 8.3.20+)

Если ваша платформа позволяет использовать современные возможности языка запросов, задачу можно решить значительно элегантнее. Проанализируем, как ROW_NUMBER() упрощает жизнь разработчику. Вместо трех временных таблиц мы можем использовать одну конструкцию ОБЛАСТЬ (PARTITION BY ...).


ВЫБРАТЬ
    Контрагенты.Ссылка,
    Контрагенты.НаименованиеПолное,
    НОМЕР_СТРОКИ() НАД(
        ПАРТИЦИЯ ПО Контрагенты.НаименованиеПолное
        УПОРЯДОЧИТЬ ПО 
            (ВЫБОР КОГДА Контрагенты.УИД_БП <> "" ТОГДА 1 ИНАЧЕ 0 КОНЕЦ) УБЫВ,
            (ВЫБОР КОГДА Контрагенты.УИД_CRM <> "" ТОГДА 1 ИНАЧЕ 0 КОНЕЦ + 
             ВЫБОР КОГДА Контрагенты.УИД_БП <> "" ТОГДА 1 ИНАЧЕ 0 КОНЕЦ + 
             ВЫБОР КОГДА Контрагенты.УИД_Торговля <> "" ТОГДА 1 ИНАЧЕ 0 КОНЕЦ) УБЫВ,
            Контрагенты.Вес УБЫВ
    ) КАК ИндексПопулярности
ИЗ
    Справочник.Контрагенты КАК Контрагенты

В данном случае запись, у которой ИндексПопулярности = 1, автоматически становится эталоном, а все остальные записи с тем же наименованием — дублями. Это решение исключает необходимость сложных соединений и работает существенно быстрее на больших объемах данных.

Практические рекомендации

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

Таким образом, комбинируя расчет «веса» карточки и анализ источников данных, мы получаем мощный инструмент для очистки нормативно-справочной информации, который можно легко адаптировать под любые требования бизнеса.

← На главную