Поиск данных по частичному совпадению — одна из самых востребованных задач при работе с 1С:Предприятие. Бухгалтеры ищут контрагентов по фрагменту названия, кладовщики — товары по артикулу, а программисты строят сложные отчеты с фильтрацией по подстрокам. Однако стандартный оператор = здесь не поможет: он требует точного совпадения. В этой статье разберем все способы выборки по подстроке — от базовых операторов ПОДОБНО и СОДЕРЖИТ до продвинутых техник с регулярными выражениями и оптимизацией производительности.
Особое внимание уделим типичным ошибкам, которые приводят к медленным запросам или некорректным результатам. Например, почему ПОДОБНО "%текст%" может вернуть лишние строки, как правильно эскапировать спецсимволы в шаблонах, и почему иногда лучше использовать ЛЕВ/ПРАВ вместо СОДЕРЖИТ. В конце статьи — практические примеры для 1С:Бухгалтерия 3.0, 1С:УТ 11 и 1С:ЗУП 3.1.
Базовые операторы для поиска подстрок: ПОДОБНО vs СОДЕРЖИТ
В языке запросов 1С есть два основных оператора для работы с подстроками: ПОДОБНО и СОДЕРЖИТ. Их часто путают, но они решают разные задачи:
- 🔍
ПОДОБНО— использует шаблоны с подстановочными знаками (%для любой последовательности символов,_для одного символа). Пример:ПОДОБНО "Иван%"найдет "Иванов", "Иванова", "Иваненко". - 📌
СОДЕРЖИТ— проверяет наличие подстроки в любом месте строки. Пример:СОДЕРЖИТ "ООО"найдет "ООО Ромашка" и "Цветы ООО".
Ключевое отличие: ПОДОБНО чувствителен к регистру (если не использовать РАЗНОСТЬ), а СОДЕРЖИТ — нет. Также ПОДОБНО поддерживает экранирование спецсимволов через ЭКРАНИРОВАТЬ, что важно при поиске по символам %, _ или [.
| Оператор | Пример | Найдет | Не найдет |
|---|---|---|---|
ПОДОБНО |
ПОДОБНО "А%" |
"Альфа", "А100" | "Бетта", "1А" |
СОДЕРЖИТ |
СОДЕРЖИТ "ООО" |
"ООО Вега", "ТоргООО" | "АО", "ИП" |
ПОДОБНО с экранированием |
ПОДОБНО ЭКРАНИРОВАТЬ("50%") |
"50%" (точное совпадение) | "50", "500" |
Важно: оператор СОДЕРЖИТ не поддерживает подстановочные знаки — для этого всегда используйте ПОДОБНО.
Продвинутые техники: регулярные выражения и функции строк
Когда стандартных операторов недостаточно, на помощь приходят регулярные выражения (через функцию РЕГВЫРАЖЕНИЕ) и функции работы со строками. Например:
- 🔤
ЛЕВ(Поле, 3) = "АБВ"— проверка первых 3 символов. - 🔠
ПРАВ(Поле, 2) = "19"— проверка последних 2 символов. - 🔡
НАЙТИ(Поле, "текст") > 0— альтернативаСОДЕРЖИТс возможностью указать позицию. - 🔢
РЕГВЫРАЖЕНИЕ(Поле, "[А-Я]{3}\d{4}")— поиск по шаблону (например, "АБВ1234").
Регулярные выражения особенно полезны для валидации форматов. Например, чтобы найти номера телефонов в формате +7 (XXX) XXX-XX-XX, используйте:
ГДЕ РЕГВЫРАЖЕНИЕ(Контакты.Телефон, "\+7 \(\d{3}\) \d{3}-\d{2}-\d{2}")
Но будьте осторожны: регулярные выражения могут значительно замедлить запрос, особенно на больших таблицах. Всегда тестируйте производительность на реальных данных.
Если вам нужно найти строки, начинающиеся с цифры, но ПОДОБНО работает слишком медленно, попробуйте комбинацию ЛЕВ(Поле, 1) >= "0" И ЛЕВ(Поле, 1) <= "9" — это часто быстрее.
Оптимизация запросов с подстроками: индексы и альтернативные подходы
Запросы с ПОДОБНО или СОДЕРЖИТ часто становятся узким местом производительности. Проблема в том, что СУБД не может эффективно использовать индексы для таких условий. Вот как это исправить:
- Используйте префиксный поиск:
ПОДОБНО "текст%"работает быстрее, чем"%текст%", так как может задействовать индексы. - Разбивайте условия: вместо
СОДЕРЖИТ "АБВ"используйтеНАЙТИ(Поле, "АБВ") > 0— иногда это быстрее. - Добавьте вычисляемое поле: если часто ищете по подстроке, создайте поле с хэшем или префиксом и индексируйте его.
Пример оптимизированного запроса для поиска контрагентов по части названия:
ВЫБРАТЬ
Контрагенты.Ссылка КАК Ссылка,
Контрагенты.Наименование КАК Наименование
ИЗ
Справочник.Контрагенты КАК Контрагенты
ГДЕ
НАЧИНАЕТСЯ С Контрагенты.Наименование С "ООО" // Использует индекс
ИЛИ СОДЕРЖИТ Контрагенты.Наименование "ЗАО" // Без индекса, но редкое условие
Указан префиксный поиск (текст%) вместо %текст%|
Использованы функции ЛЕВ/ПРАВ вместо СОДЕРЖИТ где возможно|
Добавлены индексы на поля, участвующие в поиске|
Тестировалась производительность на реальных данных-->
Внимание: если вы работаете с 1С:Управление торговлей 11 или 1С:ERP, обратите внимание на механизм полнотекстового поиска (через ПОЛНЫЙТЕКСТ). Он специально оптимизирован для поиска по подстрокам в больших объемах данных, но требует предварительной настройки индексов.
Типичные ошибки и как их избежать
Даже опытные разработчики допускают ошибки при работе с подстроками в 1С. Вот самые распространенные:
⚠️ Внимание: Если вы используетеПОДОБНОс шаблоном"%текст%"на поле типаСтрока(1000), запрос может вернуть неожиданные результаты из-за неявного приведения типов. Всегда явно указывайте длину строки или используйтеВРЕГ(Поле)для приведения к верхнему регистру.
- ❌ Игнорирование регистра:
ПОДОБНО "текст"не найдет "ТЕКСТ" или "Text". Решение:ПОДОБНО ВРЕГ(Поле) ВРЕГ("текст"). - ❌ Экранирование спецсимволов: поиск по
"50%"безЭКРАНИРОВАТЬнайдет все строки, содержащие "50". - ❌ Чрезмерное использование %: шаблон
"%а%б%в%"крайне неэффективен — лучше разбить на несколько условий.
Еще одна распространенная проблема — некорректная работа с NULL. Если поле может быть не заполнено, всегда добавляйте проверку:
ГДЕ (Поле ПОДОБНО "текст%" ИЛИ Поле ЕСТЬ NULL)
Почему ПОДОБНО может вернуть лишние строки?
Оператор ПОДОБНО в 1С использует внутреннюю логику СУБД, которая может не учитывать национальные символы или регистр так, как вы ожидаете. Например, поиск по "ё" может не найти "е", и наоборот. Для надежности всегда нормализуйте строки (приводите к верхнему регистру и заменяйте "ё" на "е") перед сравнением.
Практические примеры для типовых конфигураций
Разберем реальные кейсы из популярных конфигураций 1С:
1. Поиск товаров по артикулу в 1С:Управление торговлей 11
Задача: найти все товары, артикул которых содержит "ART-2023".
ВЫБРАТЬ
Номенклатура.Ссылка КАК Ссылка,
Номенклатура.Артикул КАК Артикул,
Номенклатура.Наименование КАК Наименование
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
Номенклатура.Артикул СОДЕРЖИТ "ART-2023"
2. Фильтрация документов по номеру в 1С:Бухгалтерия 3.0
Задача: выбрать все счета-фактуры с номерами, начинающимися на "СФ-00".
ВЫБРАТЬ
Документ.Ссылка КАК Ссылка,
Документ.Номер КАК Номер
ИЗ
Документ.СчетФактураВыданный КАК Документ
ГДЕ
Документ.Номер ПОДОБНО "СФ-00%"
3. Поиск сотрудников по ФИО в 1С:Зарплата и Управление Персоналом 3.1
Задача: найти всех Ивановых (независимо от отчества).
ВЫБРАТЬ
Сотрудник.Ссылка КАК Ссылка,
Сотрудник.ФИО КАК ФИО
ИЗ
Справочник.Сотрудники КАК Сотрудник
ГДЕ
Сотрудник.ФИО ПОДОБНО "Иванов%"
Для сложных ФИО (например, двойные фамилии) лучше использовать регулярные выражения:
ВЫБРАТЬ
Сотрудник.Ссылка КАК Ссылка
ИЗ
Справочник.Сотрудники КАК Сотрудник
ГДЕ
РЕГВЫРАЖЕНИЕ(Сотрудник.ФИО, "(^|\s)Иванов(\s|$)")
Для поиска по ФИО в 1С:ЗУП всегда учитывайте возможные варианты записи (например, "Иванов-Петров" или "Иванова (ур. Сидорова)"). Регулярные выражения здесь надежнее, чем ПОДОБНО.
Альтернативные подходы: временные таблицы и программный код
Если запрос с подстроками работает слишком медленно, рассмотрите альтернативные методы:
- Временные таблицы: предварительно отфильтруйте данные в программном коде и загрузите во временную таблицу.
- Построчный обход: для небольших выборок (до 1000 строк) иногда быстрее использовать цикл
Для Каждогос проверкой черезНАЙТИ. - Полнотекстовый поиск: если используете SQL-сервер, настройте полнотекстовые индексы и используйте
CONTAINS.
Пример с временной таблицей:
// 1. Создаем временную таблицу в программном коде
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Контрагенты.Ссылка КАК Ссылка
|ПОМЕСТИТЬ ВТКонтрагенты
|ИЗ
| Справочник.Контрагенты КАК Контрагенты
|ГДЕ
| НАЧИНАЕТСЯ С Контрагенты.Наименование С ""ООО""";
Запрос.Выполнить();
// 2. Дальше работаем с отфильтрованными данными
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ВТКонтрагенты.Ссылка КАК Ссылка,
| Контрагенты.ИНН КАК ИНН
|ИЗ
| ВТКонтрагенты КАК ВТКонтрагенты
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Контрагенты
| ПО ВТКонтрагенты.Ссылка = Контрагенты.Ссылка";
Внимание: временные таблицы занимают память сервера. Всегда очищайте их после использования командой УничтожитьОбъекты().
Производительность: что действительно работает
Чтобы ускорить запросы с подстроками, следуйте этим правилам:
- ⚡ Избегайте
%текст%: используйтетекст%или%текст(но не оба одновременно). - ⚡ Ограничивайте выборку: добавьте дополнительные условия (например, по дате или статусу).
- ⚡ Используйте функции строк:
ЛЕВ/ПРАВчасто быстрее, чемСОДЕРЖИТ. - ⚡ Тестируйте на реальных данных: производительность может сильно отличаться в зависимости от СУБД (SQL Server, PostgreSQL, файловый вариант).
Сравнение скорости на примере поиска по 100 000 строк:
| Метод | SQL Server | PostgreSQL | Файловый |
|---|---|---|---|
ПОДОБНО "текст%" |
0.1 с | 0.08 с | 1.2 с |
СОДЕРЖИТ "текст" |
0.4 с | 0.3 с | 2.5 с |
ЛЕВ(Поле, 5) = "текст" |
0.05 с | 0.04 с | 0.8 с |
Как видно из таблицы, ЛЕВ/ПРАВ часто оказываются самым быстрым вариантом, особенно в файловом варианте 1С.
FAQ: Ответы на частые вопросы
Можно ли в одном запросе использовать и ПОДОБНО, и СОДЕРЖИТ?
Да, но это может снизить производительность. Например:
ГДЕ (Поле1 ПОДОБНО "А%" ИЛИ Поле2 СОДЕРЖИТ "Б")
Лучше разбить такой запрос на два отдельных и объединить результаты через ОБЪЕДИНИТЬ.
Почему запрос с ПОДОБНО возвращает строки, которые не подходят под шаблон?
Это может происходить из-за:
- Неявного приведения типов (например, сравнение строки с числом).
- Особенностей обработки национальных символов (например, "ё" и "е" могут считаться эквивалентными).
- Наличия непечатаемых символов в данных (пробелов, табуляций).
Решение: используйте ВРЕГ для нормализации регистра и СОКРЛП для удаления пробелов.
Как искать по подстроке в динамическом списке?
В динамических списках 1С можно использовать параметры отбора с оператором Содержит:
Отбор.Добавить("Наименование", ТипОтбора.Содержит, "текст");
Для сложных условий создайте вычисляемое поле в запросе динамического списка.
Есть ли разница между ПОДОБНО в файловом и клиент-серверном варианте 1С?
Да, в клиент-серверном варианте (особенно с SQL Server) запрос ПОДОБНО транслируется в LIKE SQL, который может использовать индексы для префиксного поиска ("текст%"). В файловом варианте индексы не работают, и поиск всегда полносканирует таблицу.
Как эскапировать спецсимволы в шаблонах ПОДОБНО?
Используйте функцию ЭКРАНИРОВАТЬ:
ГДЕ Поле ПОДОБНО ЭКРАНИРОВАТЬ("50% скидка_")
Это заменит %, _ и [ на экранированные последовательности.