Как найти документы или элементы справочников с идентичной табличной частью в 1С?

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

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

Метод 1. Сравнение через временные таблицы в запросе

Разберем самый распространенный способ, который не требует изменения структуры конфигурации. Идея заключается в использовании метода «двойного вхождения». Для того чтобы две табличные части (ТЧ) считались идентичными, должны выполняться три условия: количество строк совпадает, все строки эталона есть в цели, и в цели нет лишних строк. Проанализируем, как реализовать это в коде запроса.

Рассмотрим пошагово алгоритм реализации:

  1. Выгружаем табличную часть текущего (нового) документа в таблицу значений.
  2. Помещаем эту таблицу во временную таблицу в запросе (например, ВТ_Эталон).
  3. Выполняем соединение ВТ_Эталон с табличной частью существующих документов в базе.

Пример реализации запроса для поиска документа-дубля:


ВЫБРАТЬ
    ТЧ_Документа.Ссылка КАК Ссылка,
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ТЧ_Документа.НомерСтроки) КАК КолВоСтрок
ПОМЕСТИТЬ ВТ_Кандидаты
ИЗ
    Документ.МаршрутныйЛист.ПунктыСледования КАК ТЧ_Документа
ГДЕ
    ТЧ_Документа.Пункт В (ВЫБРАТЬ Пункт ИЗ ВТ_Эталон)
СГРУППИРОВАТЬ ПО
    ТЧ_Документа.Ссылка;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Кандидаты.Ссылка
ИЗ
    ВТ_Кандидаты КАК Кандидаты
ГДЕ
    Кандидаты.КолВоСтрок = &ОбщееКолВоСтрокЭталона
    И НЕ Ссылка В (
        ВЫБРАТЬ
            ТЧ.Ссылка
        ИЗ
            Документ.МаршрутныйЛист.ПунктыСледования КАК ТЧ
            ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Эталон КАК Эталон
            ПО ТЧ.Пункт = Эталон.Пункт
            И ТЧ.НомерСтроки = Эталон.НомерСтроки
        ГДЕ
            Эталон.Пункт ЕСТЬ NULL
    )

В данном примере мы сначала отбираем документы, которые содержат нужные нам пункты, а затем отсеиваем те, где количество строк отличается от эталона или где есть строки, не соответствующие эталону по ключевым полям и позиции (НомерСтроки).

Метод 2. Использование контрольных сумм (Хеширование)

Если база данных содержит десятки тысяч документов, и поиск должен выполняться мгновенно, использование временных таблиц может замедлить систему. Рассмотрим более продвинутый метод — создание индексированного поля с хеш-суммой состава ТЧ. Выясним причину эффективности этого метода: поиск по одному числу или короткой строке всегда быстрее, чем сопоставление множества строк в таблицах.

Порядок реализации:

  1. Добавим в документ или справочник реквизит ХешТЧ (тип Строка или Число) и установим для него свойство «Индексировать».
  2. При записи объекта создадим строку, состоящую из идентификаторов всех строк ТЧ. Важно предварительно отсортировать строки, если порядок не важен, или оставить как есть, если порядок критичен.
  3. Применим функцию вычисления хеша (например, MD5 или CRC32).

Посмотрим на пример формирования строки для хеша:


Функция СформироватьХешТабличнойЧасти(ТабличнаяЧасть)
    ТекстДляХеша = "";
    // Если порядок не важен, сначала сортируем ТЧ по ключевому полю
    // ТабличнаяЧасть.Сортировать("Пункт"); 
    
    Для Каждого СтрокаТЧ Из ТабличнаяЧасть Цикл
        ТекстДляХеша = ТекстДляХеша + "_" + Строка(СтрокаТЧ.Пункт.УникальныйИдентификатор());
        ТекстДляХеша = ТекстДляХеша + "_" + Формат(СтрокаТЧ.Количество, "ЧГ=0");
    КонецЦикла;
    
    // Используем встроенные средства или сторонние библиотеки для MD5
    Возврат ПолучитьХешСтроки(ТекстДляХеша); 
КонецФункции

Теперь поиск сводится к простому запросу: ГДЕ ХешТЧ = &ПараметрХеш. Это гарантирует мгновенное получение результата вне зависимости от объема данных.

Метод 3. Оптимизация структуры (Регистры сведений)

Проанализируем ситуацию, когда данные ТЧ часто меняются или используются для сложной аналитики. В таких случаях данные ТЧ целесообразно дублировать в Регистр сведений. Это позволяет строить более гибкие индексы.

В контексте обсуждения на форуме, где упоминался справочник Маршруты, правильным архитектурным решением будет создание табличной части в самом справочнике. Если же мы хотим найти «Маршрут» по набору пунктов из документа, мы можем использовать механизм «Ключей аналитики». Мы создаем справочник-ключ, где каждый элемент соответствует уникальному набору строк ТЧ. В документе мы просто храним ссылку на этот ключ.

Важные нюансы при сравнении

При реализации любого из методов необходимо учитывать следующие моменты:

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

← На главную