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