Как реализовать поиск по вхождению подстроки в запросах 1С для категоризации данных

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

В практике разработчика 1С часто возникает задача сопоставления "грязных" или неструктурированных данных (например, загруженных из Excel) с существующими справочниками системы. Типичный пример: в строке указано «Компьютер Acer 5232», и программу нужно «научить» автоматически определять, что этот элемент относится к группе «Компьютеры» или «Системные блоки». Рассмотрим подробнее, как эффективно реализовать такой поиск с помощью механизмов платформы 1С.

Использование оператора ПОДОБНО в запросах

Основным инструментом для поиска подстроки в языке запросов 1С является оператор ПОДОБНО. Он позволяет сравнивать строковое поле с шаблоном, где используются специальные символы маски:

  1. % (процент) — заменяет любую последовательность произвольных символов.
  2. _ (подчеркивание) — заменяет один произвольный символ.

Проанализируем ситуацию, когда нам нужно найти все наименования, содержащие слово «Компьютер». В коде запроса это будет выглядеть следующим образом:


Запрос.Текст = 
    "ВЫБРАТЬ
    |   Номенклатура.Наименование КАК Наименование
    |ИЗ
    |   Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |   Номенклатура.Наименование ПОДОБНО ""%Компьютер%""";

Важно помнить, что использование процента в начале шаблона (%Текст) лишает СУБД возможности использовать индексы, что может привести к замедлению работы на больших таблицах. Если бизнес-логика позволяет искать только по началу строки, лучше использовать шаблон Текст%.

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

Когда данные для поиска находятся не в базе, а во внешней таблице (например, в ТаблицаЗначений), разберем по шагам правильный алгоритм действий. Нельзя просто перебирать таблицу в цикле и выполнять запрос на каждой итерации — это крайне неэффективно. Правильный путь — передать всю таблицу в запрос и выполнить соединение на уровне базы данных.

Выясним причину, по которой новички часто совершают ошибки на этом этапе. Для корректной работы со строками неограниченной длины или длинными строками в ТаблицаЗначений их необходимо приводить к фиксированной длине с помощью функции ПОДСТРОКА. Рассмотрим пример подготовки и передачи таблицы в запрос:


// Подготовим таблицу значений с данными из Excel
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Наименование", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(200)));

// Заполним таблицу...
// ...

МенеджерВТ = Новый МенеджерВременныхТаблиц;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВТ;

// Шаг 1: Помещаем ТЗ во временную таблицу
Запрос.Текст = 
    "ВЫБРАТЬ
    |   ПОДСТРОКА(ТЗ.Наименование, 1, 200) КАК НаименованиеДляПоиска
    |ПОМЕСТИТЬ ВТ_ДанныеExcel
    |ИЗ
    |   &ТЗ КАК ТЗ";

Запрос.УстановитьПараметр("ТЗ", ТЗ);
Запрос.Выполнить();

Сложное соединение таблиц по условию вхождения

Теперь посмотрим на пример финального запроса, который сопоставит наши данные из временной таблицы со справочником категорий. Обратите внимание на конструкцию соединения — мы будем использовать условие ПОДОБНО непосредственно в секции ПО.


Запрос2 = Новый Запрос;
Запрос2.МенеджерВременныхТаблиц = МенеджерВТ;
Запрос2.Текст = 
    "ВЫБРАТЬ
    |   ВТ.НаименованиеДляПоиска КАК ИсходнаяСтрока,
    |   Группы.Ссылка КАК НайденнаяГруппа
    |ИЗ
    |   ВТ_ДанныеExcel КАК ВТ
    |       ЛЕВОЕ СОЕДИНЕНИЕ Справочник.КатегорииТоваров КАК Группы
    |       ПО (ВТ.НаименованиеДляПоиска ПОДОБНО ""%"" + Группы.Наименование + ""%"")";

Результат = Запрос2.Выполнить().Выбрать();
Пока Результат.Следующий() Цикл
    // Здесь мы получаем результат сопоставления
    // Если НайденнаяГруппа = NULL, значит вхождение не найдено
КонецЦикла;

Проанализируем ситуацию с "размножением" строк (кросс-соединение). Если в исходной строке «Компьютер и Принтер» встретятся ключевые слова сразу из двух групп («Компьютеры» и «Принтеры»), запрос вернет две записи для одной исходной строки. Чтобы этого избежать, рассмотрим подробнее использование группировки:


Запрос.Текст = 
    "ВЫБРАТЬ
    |   ВТ.НаименованиеДляПоиска КАК ИсходнаяСтрока,
    |   МИНИМУМ(Группы.Ссылка) КАК НайденнаяГруппа
    |ИЗ
    |   ВТ_ДанныеExcel КАК ВТ
    |       ЛЕВОЕ СОЕДИНЕНИЕ Справочник.КатегорииТоваров КАК Группы
    |       ПО (ВТ.НаименованиеДляПоиска ПОДОБНО ""%"" + Группы.Наименование + ""%"")
    |СГРУППИРОВАТЬ ПО
    |   ВТ.НаименованиеДляПоиска";

Альтернативные методы: СТРНАЙТИ и Полнотекстовый поиск

Начиная с версии платформы 8.3.20, функция СТРНАЙТИ стала доступна непосредственно в тексте запроса. Это делает код более читаемым и иногда более производительным. Посмотрим на пример использования этой функции:


|ВЫБРАТЬ
|   Таблица.Наименование
|ИЗ
|   Таблица КАК Таблица
|ГДЕ
|   СТРНАЙТИ(Таблица.Наименование, ""Компьютер"") > 0

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

Обработка спецсимволов

При использовании ПОДОБНО важно учитывать, что в самих наименованиях товаров могут содержаться символы, которые язык запросов интерпретирует как служебные (например, "%" в названии "Спирт 95%"). В таких случаях необходимо использовать ключевое слово СПЕЦСИМВОЛ. Рассмотрим подробнее:


// Если мы ищем строку, содержащую символ "%"
// Используем "/" как экранирующий символ
Запрос.Текст = "ГДЕ Номенклатура.Наименование ПОДОБНО ""%95/%"" СПЕЦСИМВОЛ ""/""";

Подведем итог: поиск по вхождению в строке — это мощный инструмент для автоматизации сопоставления данных. Комбинируя временные таблицы, оператор ПОДОБНО и правильные типы соединений, можно значительно ускорить процесс обработки входящей информации и минимизировать ручной труд пользователя.

← На главную