В практике разработки на платформе 1С:Предприятие часто возникают ситуации, когда запрос, казалось бы, написанный верно, возвращает «лишние» строки. Одной из самых коварных ошибок является неправильное сочетание логических операторов И (AND) и ИЛИ (OR). Рассмотрим ситуацию, когда при наличии условия по конкретному менеджеру в выборку все равно попадают данные других сотрудников.
Проанализируем фрагмент запроса, который вызывал затруднения. Разработчик хотел получить контактную информацию контрагентов, закрепленных за определенным менеджером, при условии, что в поле адреса (Поле4) встречаются названия определенных городов.
Посмотрим на исходный код условия в блоке ГДЕ:
ГДЕ
(Контрагенты.Менеджер = &Менеджер
И КонтактнаяИнформация.Поле4 <> &Поле4
И КонтактнаяИнформация.Поле4 ПОДОБНО "%Сатка%"
ИЛИ КонтактнаяИнформация.Поле4 ПОДОБНО "%Усть-Катав%"
ИЛИ КонтактнаяИнформация.Поле4 ПОДОБНО "%Аша%"
ИЛИ КонтактнаяИнформация.Поле4 ПОДОБНО "%Катав-Ивановск%"
ИЛИ КонтактнаяИнформация.Поле4 ПОДОБНО "%Куса%")
На первый взгляд кажется, что все условия находятся внутри общих скобок и должны работать совместно. Однако здесь вступает в силу правило приоритета логических операций. В языке запросов 1С (как и в стандартном SQL) оператор И имеет более высокий приоритет, чем оператор ИЛИ. Это означает, что система сначала вычисляет цепочку условий, соединенных через И, а затем объединяет результат с условиями через ИЛИ.
Фактически, система прочитала условие следующим образом:
Именно поэтому в итоговый результат попадали строки с другими менеджерами: они удовлетворяли условиям, стоящим после первого оператора ИЛИ.
Чтобы заставить фильтр по менеджеру работать для всех городов, нам необходимо явно указать порядок выполнения операций. Мы должны «сгруппировать» все условия по городам в один блок, чтобы менеджер применялся к результату этого блока. Рассмотрим исправленный вариант:
ГДЕ
Контрагенты.Менеджер = &Менеджер
И (КонтактнаяИнформация.Поле4 ПОДОБНО "%Сатка%"
ИЛИ КонтактнаяИнформация.Поле4 ПОДОБНО "%Усть-Катав%"
ИЛИ КонтактнаяИнформация.Поле4 ПОДОБНО "%Аша%"
ИЛИ КонтактнаяИнформация.Поле4 ПОДОБНО "%Катав-Ивановск%"
ИЛИ КонтактнаяИнформация.Поле4 ПОДОБНО "%Куса%")
Теперь логика работы изменилась. Теперь И соединяет конкретного менеджера с результатом всей группы условий в скобках. Теперь, какой бы город ни нашелся, система обязательно проверит, соответствует ли контрагент выбранному менеджеру.
Рассматривая этот запрос, мы должны обратить внимание на еще одну важную деталь. В тексте используется ЛЕВОЕ СОЕДИНЕНИЕ регистра сведений со справочником контрагентов. Однако фильтрация по менеджеру происходит в блоке ГДЕ.
Выясним причину, почему это важно: когда мы накладываем условие на поле из правой таблицы (Контрагенты) в блоке ГДЕ, наше ЛЕВОЕ СОЕДИНЕНИЕ фактически превращается во ВНУТРЕННЕЕ. Если в регистре есть запись, для которой контрагент не найден (или поле Объект пустое), поле Менеджер будет содержать NULL. Сравнение NULL = &Менеджер всегда дает результат Ложь, и такие записи будут отсечены.
Если ваша задача — сохранить в результате все записи контактной информации (даже без контрагентов), но для существующих контрагентов проверить менеджера, условие нужно перенести из блока ГДЕ в условие связи ПО:
ИЗ
РегистрСведений.КонтактнаяИнформация КАК КонтактнаяИнформация
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Контрагенты
ПО КонтактнаяИнформация.Объект = Контрагенты.Ссылка
И Контрагенты.Менеджер = &Менеджер
Проанализируем использование конструкции ПОДОБНО "%Текст%". Использование символа процента в начале строки поиска является крайне ресурсоемкой операцией для базы данных. Важно помнить: такие условия не могут использовать индексы. СУБД будет вынуждена выполнить полное сканирование таблицы (Full Scan), что на больших объемах данных (например, в регистре с миллионами записей контактной информации) приведет к существенным тормозам.
Если вам часто требуется подобный поиск, рекомендуется рассмотреть следующие варианты:
ИЛИ с оператором ПОДОБНО.В исходном запросе используется СГРУППИРОВАТЬ ПО без агрегатных функций. Это классический способ избавиться от дублирующихся строк, когда у одного контрагента может быть несколько записей контактной информации, подходящих под фильтр. Однако, если Поле4 содержит длинные строки (адреса), группировка по нему может быть медленной. В таких случаях иногда эффективнее использовать ключевое слово ВЫБРАТЬ РАЗЛИЧНЫЕ, хотя с точки зрения производительности на уровне SQL это часто приводит к схожим планам выполнения запроса.
Подводя итог: всегда следите за приоритетами И над ИЛИ и не забывайте, что скобки в запросах — это не просто средство оформления, а инструмент управления логикой выборки данных.