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

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

В практике разработчика 1С часто возникает задача поиска данных по текстовым полям. Типичный пример: нужно найти все записи, содержащие фразу «Договор аренды». Казалось бы, задача простая, но на практике в наименованиях часто встречаются опечатки в виде двух, трех или более пробелов между словами. При этом стандартный поиск через маску %Договор%аренды% не подходит, так как под него подпадут нежелательные строки, такие как «Договор субаренды» или «Договор купли-продажи и аренды».

В этой статье мы подробно разберем, как реализовать условие «только пробелы в любом количестве» между двумя словами, используя стандартный язык запросов 1С и оператор ПОДОБНО.

Ограничения оператора ПОДОБНО и почему обычные маски не работают

Давайте проанализируем ситуацию. Оператор ПОДОБНО в 1С использует ограниченный набор спецсимволов. Символ процента % означает любую последовательность любых символов (включая цифры и буквы), а символ подчеркивания _ — ровно один любой символ. К сожалению, в языке запросов 1С, в отличие от регулярных выражений, нет квантификаторов, которые позволяют задать условие «один или более конкретных символов» (например, \s+).

Если мы напишем:

ГДЕ Наименование ПОДОБНО "%Договор%аренды%"

Запрос вернет и «Договор аренды», и «Договор субаренды», и «Договор2936234987 аренды». Это происходит потому, что % «проглатывает» любые символы между ключевыми словами.

Способ 1: Использование квадратных скобок для перечисления вариантов

Рассмотрим первый, наиболее очевидный, но трудоемкий способ. Оператор ПОДОБНО поддерживает использование квадратных скобок [...], внутри которых можно указать допустимые одиночные символы. Мы можем составить запрос, который учитывает фиксированное количество пробелов через условие ИЛИ.

Разберем пример такого кода:


ГДЕ ВТ_Данные.Наименование ПОДОБНО "%Договор[ ]аренды%"
    ИЛИ ВТ_Данные.Наименование ПОДОБНО "%Договор[ ][ ]аренды%"
    ИЛИ ВТ_Данные.Наименование ПОДОБНО "%Договор[ ][ ][ ]аренды%"

Преимущества: это решение наглядно и работает «из коробки».

Недостатки: мы ограничены тем количеством пробелов, которое прописали вручную. Если пользователь введет 10 пробелов, запрос такую строку уже не найдет. Кроме того, такой подход раздувает текст запроса и снижает его читаемость.

Способ 2: Оптимальное решение через отрицание символов

Теперь выясним, как решить задачу элегантно, чтобы количество пробелов могло быть любым, но при этом между словами не было ничего, кроме них. Для этого мы применим логическую связку двух условий: разрешающего и запрещающего.

Проанализируем логику:

  1. Первым условием мы гарантируем, что в строке есть слова «Договор» и «аренды», разделенные хотя бы одним пробелом.
  2. Вторым условием мы отсекаем (через НЕ ПОДОБНО) все варианты, где между этими словами встречается любой символ, кроме пробела.

Для реализации исключения используется конструкция [^ ], где символ ^ внутри квадратных скобок означает отрицание. Посмотрим на реализацию в коде:


ВЫБРАТЬ
    Спр.Ссылка
ИЗ
    Справочник.ДоговорыКонтрагентов КАК Спр
ГДЕ
    Спр.Наименование ПОДОБНО "%Договор %аренды%"
    И НЕ Спр.Наименование ПОДОБНО "%Договор%[^ ]%аренды%"

Разберем по шагам, как это работает:

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

Способ 3: Проблема неразрывных пробелов

Часто при копировании текста из документов Word или веб-страниц в базу 1С попадают так называемые «неразрывные пробелы» (символ с кодом 160). Обычный пробел (код 32) и неразрывный пробел для системы — это разные символы.

Чтобы наш поиск был по-настоящему профессиональным, мы должны учитывать оба варианта. Давайте модернизируем наше решение, добавив неразрывный пробел в набор допустимых символов:


ГДЕ
    (Спр.Наименование ПОДОБНО "%Договор %аренды%" ИЛИ Спр.Наименование ПОДОБНО "%Договор[ ]%аренды%")
    И НЕ Спр.Наименование ПОДОБНО "%Договор%[^  ]%аренды%"

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

Альтернатива: Полнотекстовый поиск (ПП)

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

В таких случаях стоит рассмотреть механизм Полнотекстового поиска 1С. Рассмотрим его особенности:

Однако помните, что полнотекстовый индекс требует регулярного обновления (регламентным заданием), иначе вы не найдете только что созданные документы.

Рекомендации по производительности

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

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

Это позволит вам использовать простое равенство или поиск ПОДОБНО "Договор аренды%" (без процента в начале), что обеспечит мгновенную работу системы благодаря индексам.

Таким образом, мы рассмотрели несколько подходов к решению задачи. Для разовых задач или небольших справочников идеально подходит Способ 2 с использованием отрицания [^ ], а для высоконагруженных систем лучшим выбором станет предварительная нормализация данных или использование механизмов полнотекстового поиска.

← На главную