Почему оператор ПОДОБНО в запросе 1С возвращает не все данные?

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

При работе с запросами в системе 1С:Предприятие программисты часто сталкиваются с ситуацией, когда оператор ПОДОБНО (аналог SQL-оператора LIKE) ведет себя непредсказуемо. Казалось бы, логика фильтрации проста, но часть записей «исчезает» из итоговой выборки. Особенно часто это проявляется при использовании отрицания НЕ ПОДОБНО. В этой статье мы подробно разберем, почему так происходит, проанализируем типичные ошибки в коде и выясним, как правильно строить условия фильтрации.

Проблема трехзначной логики и значения NULL

Разберем самую коварную причину «пропажи» записей — наличие значений NULL в базе данных. В стандартной логике мы привыкли к двум состояниям: «Истина» или «Ложь». Однако SQL-серверы, на которых работает 1С, используют трехзначную логику. Любое сравнение с NULL (включая ПОДОБНО) возвращает результат «Неизвестно» (Unknown).

Проанализируем ситуацию: если в поле Код содержится NULL, то условие Код ПОДОБНО "%Б%" будет ложным. Но, что менее очевидно, условие НЕ Код ПОДОБНО "%Б%" также не будет истинным для этой записи. В результате строка просто исключается из выборки. Рассмотрим, как правильно обработать это в запросе:


ГДЕ
    (НЕ РаботаОбороты.Код ПОДОБНО "%Б%")
    ИЛИ (РаботаОбороты.Код ЕСТЬ NULL)

Используя такую конструкцию, мы гарантируем, что записи с незаполненными кодами не будут потеряны при наложении отрицательного фильтра.

Особенности работы с виртуальными таблицами

В тексте запроса автора используется виртуальная таблица РегистрНакопления.Работа.Обороты. Важно понимать разницу между наложением фильтра в параметрах виртуальной таблицы и в секции ГДЕ. Когда мы пишем условие после ключевого слова ГДЕ, система сначала получает все данные из оборотов, а затем начинает их фильтровать. Это не только замедляет работу, но и может приводить к ошибкам при левых соединениях.

Посмотрим на пример правильного наложения фильтра, если Код является измерением или реквизитом, доступным в параметрах:


ВЫБРАТЬ
    РаботаОбороты.Код,
    РаботаОбороты.Период,
    РаботаОбороты.СуммаОборот
ИЗ
    РегистрНакопления.Работа.Обороты(&Дата1, &Дата2, , Прод = &Прод) КАК РаботаОбороты
ГДЕ
    НЕ РаботаОбороты.Код ПОДОБНО "%Б%"

Ошибки в логике соединений таблиц

Часто записи «теряются» не из-за самого оператора ПОДОБНО, а из-за того, как связаны таблицы в сложном запросе. Если мы используем ЛЕВОЕ СОЕДИНЕНИЕ и накладываем жесткое условие на правую таблицу в секции ГДЕ, наше левое соединение фактически превращается во ВНУТРЕННЕЕ СОЕДИНЕНИЕ.

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

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

Влияние кодировок и раскладки клавиатуры

Выясним причину, связанную с человеческим фактором и визуальной схожестью символов. В кириллице и латинице есть буквы, которые выглядят идентично: «А», «В», «С», «Е», «Н», «О», «Р», «Х». Если часть кодов в справочнике была введена на английской раскладке, а в запросе мы ищем русскую «Б» (или наоборот), оператор ПОДОБНО проигнорирует такие записи.

Также стоит обратить внимание на:

  1. Пробелы: Если поле имеет фиксированную длину, в конце строки могут быть невидимые пробелы. Использование маски "%Б%" обычно решает эту проблему, но при поиске по началу строки "Б%" пробелы могут мешать.
  2. Регистр: Поведение 1С зависит от используемой СУБД. На MS SQL Server поиск обычно нечувствителен к регистру, а на PostgreSQL (часто используемом в связке с Linux) — чувствителен. Для надежности рекомендуется приводить поле к единому регистру.

ГДЕ
    ВРЕГИСТР(РаботаОбороты.Код) ПОДОБНО "%Б%"

Проверка типов данных

Проанализируем еще один важный момент: типы данных сравниваемых полей. Оператор ПОДОБНО работает только со строковыми типами. Если поле Код имеет составной тип данных или является ссылкой, результат может быть непредсказуемым. Всегда используйте ВЫРАЗИТЬ(... КАК СТРОКА), если есть сомнения в типе источника:


ГДЕ
    ВЫРАЗИТЬ(РаботаОбороты.Код КАК СТРОКА(20)) ПОДОБНО "%Б%"

Итоги и рекомендации

Если ваш запрос выдает меньше результатов, чем ожидалось, выполните следующие шаги:

  1. Проверьте наличие NULL в данных и добавьте проверку ЕСТЬ NULL в условие.
  2. Убедитесь, что символы в условии запроса и в базе данных написаны в одной раскладке (кириллица/латиница).
  3. Протестируйте запрос без соединений, чтобы понять, на каком этапе «отваливаются» записи.
  4. Если используется PostgreSQL, принудительно приводите строки к верхнему регистру функцией ВРЕГИСТР().
  5. Проверьте правильность использования спецсимволов. Если в коде присутствуют символы %, _ или [, их нужно экранировать с помощью конструкции СПЕЦСИМВОЛ.

Соблюдение этих правил позволит вам писать надежные запросы и избегать трудноуловимых ошибок при фильтрации данных.

← На главную