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