Язык запросов платформы 1С:Предприятие является мощным инструментом для выборки данных, и ключевым элементом фильтрации в нем выступает оператор ГДЕ. Именно этот блок позволяет разработчику отсечь лишние записи на уровне СУБД, не перегружая память приложения обработкой ненужных объектов. Понимание механики работы условий критически важно для написания производительного кода, так как некорректное использование может привести к полному сканированию таблиц и падению быстродействия системы.

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

Базовый синтаксис и логические операторы

Оператор ГДЕ всегда располагается после предложения ИЗ и перед блоками СОРТИРОВКА ПО или ОБЪЕДИНИТЬ ВСЕ. Его задача — вернуть только те строки результата, для которых выражение условия истинно. В 1С используется стандартный набор логических операторов: И, ИЛИ, НЕ, которые позволяют строить сложные составные условия фильтрации.

Приоритет выполнения операций в 1С строго определен: сначала вычисляются сравнения (=, <, >), затем применяется отрицание НЕ, после этого конъюнкция И и в самую последнюю очередь дизъюнкция ИЛИ. Это означает, что выражение А ИЛИ Б И В будет интерпретировано как А ИЛИ (Б И В), а не как (А И Б) И В.

Для явного управления порядком вычислений необходимо использовать круглые скобки. Это особенно важно при смешивании операторов И и ИЛИ, где логика выборки может кардинально меняться в зависимости от группировки условий. Пренебрежение скобками часто приводит к тому, что в выборку попадают совершенно не те документы, которые планировал увидеть разработчик.

💡

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

Рассмотрим пример корректной группировки условий для выборки документов:

ВЫБРАТЬ

ДокументРеализацияТоваровУслуг.Ссылка

ИЗ

Документ.РеализацияТоваровУслуг КАК ДокументРеализацияТоваровУслуг

ГДЕ

(ДокументРеализацияТоваровУслуг.Проведен = ИСТИНА

ИЛИ ДокументРеализацияТоваровУслуг.ПометкаУдаления = ЛОЖЬ)

И ДокументРеализацияТоваровУслуг.Дата МЕЖДУ &НачПер И &КонПер

Работа с типами данных и сравнениями

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

Для работы с перечислениями и константами используются специальные ключевые слова: ИСТИНА, ЛОЖЬ, NULL, ЗНАЧЕНИЕ. При сравнении с перечислениями часто используется конструкция ЕСТЬNULL или прямое сравнение с символьным идентификатором, если тип поля это позволяет. Особое внимание следует уделить сравнению строк: оно выполняется с учетом регистра, если в свойствах базы данных не указано иное, но в 1С чаще всего сравнение регистронезависимое благодаря настройкам СУБД.

⚠️ Внимание: При сравнении полей типа ХранилищеЗначения или УникальныйИдентификатор убедитесь, что параметр запроса имеет тот же тип. Неявное приведение UUID к строке может привести к тому, что условие всегда будет ложным.

Сравнение дат требует понимания того, как платформа хранит время. Дата в 1С включает в себя время с точностью до секунды. Поэтому условие Дата = &МояДата сработает только если время в параметре совпадет с временем в базе до секунды. Для выборки документов за весь день лучше использовать оператор МЕЖДУ или сравнивать дату с началом и концом суток.

  • 📅 Используйте НАЧАЛОДНЯ() и КОНЕЦДНЯ() для корректной выборки документов за сутки.
  • 🔢 Для числовых полей избегайте сравнений с плавающей точкой на точное равенство из-за погрешности вычислений.
  • 📝 При сравнении строк учитывайте возможные пробелы в начале или конце значения, используйте функцию СОКРЛП().
📊 С каким типом данных у вас чаще всего возникают проблемы в условиях ГДЕ?
Дата и время
Строки и регистр
Числа и точность
Ссылки и УникальныйИдентификатор

Особенности работы с NULL и ЕСТЬNULL

Обработка пустых значений является одной из самых частых причин ошибок в запросах 1С. В логике SQL и 1С значение NULL означает «неизвестно», и оно не равно ничему, включая само себя. Выражение Поле = NULL всегда вернет ЛОЖЬ или NULL, но никогда ИСТИНА. Для проверки на пустое значение необходимо использовать специальный оператор ЕСТЬNULL.

Функция ЕСТЬNULL(Выражение, ЗаменяющееЗначение) позволяет подменить пустое значение на какое-либо другое перед сравнением. Это крайне полезно, когда нужно выбрать записи, где поле либо пусто, либо равно определенному значению. Однако стоит помнить, что использование этой функции в условии ГДЕ может негативно сказаться на использовании индексов базой данных.

Рассмотрим разницу в подходах к фильтрации:

Подход Пример кода Влияние на индекс
Прямое сравнение ГДЕ Поле = NULL Всегда ложно, индекс не используется
Оператор ЕСТЬNULL ГДЕ ЕСТЬNULL(Поле, 0) = 0 Может предотвратить использование индекса
Явная проверка ГДЕ Поле IS NULL ИЛИ Поле = 0 Оптимально для использования индексов

В 1С синтаксис проверки на NULL выглядит как Поле ЕСТЬ NULL. Это наиболее предпочтительный способ с точки зрения читаемости и часто оптимизации запроса сервером. Комбинирование условий с NULL требует аккуратности: если вы используете И, то наличие NULL в одной из частей может обнулить весь результат условия.

Почему ЕСТЬNULL может тормозить запрос?

Функция ЕСТЬNULL вычисляется для каждой строки таблицы до применения условия. Если на поле стоит индекс, обертывание его в функцию часто делает индекс бесполезным, заставляя СУБД сканировать всю таблицу.

Параметризация запросов и защита от инъекций

Использование параметров в условиях ГДЕ — это не просто вопрос удобства, а требование безопасности и производительности. Подстановка значений напрямую в текст запроса через конкатенацию строк является грубой ошибкой, открывающей путь для SQL-инъекций и мешающей кэшированию планов выполнения запроса на стороне сервера 1С.

Параметры обозначаются символом амперсанда & перед именем (например, &ПараметрКонтрагента). Значения этим параметрам присваиваются в объекте Запрос перед выполнением. Платформа сама заботится о экранировании специальных символов и приведении типов, что гарантирует целостность данных.

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

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| СправочникНоменклатура.Ссылка

|ИЗ

| Справочник.Номенклатура КАК СправочникНоменклатура

|ГДЕ

| СправочникНоменклатура.Владелец В (&СписокВладельцев)";

Запрос.УстановитьПараметр("СписокВладельцев", МассивВладельцев);

Результат = Запрос.Выполнить();

⚠️ Внимание: Никогда не формируйте текст запроса путем склеивания строк с пользовательским вводом. Это уязвимость уровня критической ошибки, позволяющая злоумышленнику получить доступ ко всей базе данных.

💡

Параметризация запросов ускоряет работу за счет кэширования плана выполнения и защищает систему от внедрения вредоносного кода.

Оптимизация условий и использование индексов

Написание условий, которые эффективно используют индексы базы данных, является высшим пилотажем разработчика 1С. Сервер 1С стремится преобразовать запрос в оптимальный SQL, но некоторые конструкции в блоке ГДЕ могут сделать это невозможным. Главное правило: избегайте применения функций к полям таблицы в левой части условия сравнения.

Если вы пишете ГДЕ ГОД(Дата) = 2023, базе данных придется вычислить функцию ГОД для каждой записи в таблице, что отключает использование индекса по полю Дата. Правильный подход — ограничить диапазон дат: ГДЕ Дата >= '20230101' И Дата < '20260101'. Это позволит СУБД быстро найти нужный диапазон по индексу.

Также стоит избегать сложных вычислений в условиях. Операции типа Поле1 + Поле2 = 100 также приводят к полному сканированию таблицы. Если такая логика необходима, рассмотрите возможность создания вычисляемого поля в конфигурации или использование временных таблиц с предварительно рассчитанными значениями.

  • 🚀 Избегайте функций (ЛЕВСИМВ, ГОД, СУММА) в левой части условия ГДЕ.
  • 🔍 Используйте оператор ПОДОБНО с осторожностью: шаблон "%Текст" отключает индекс, а "Текст%" может его использовать.
  • 📉 Проверяйте план выполнения запроса через консоль сервера или технологический журнал для анализа узких мест.

☑️ Аудит оптимизации условий

Выполнено: 0 / 4

Частые ошибки и антипаттерны

Даже опытные разработчики иногда допускают ошибки при формировании условий, которые проявляются только на больших объемах данных или в специфических сценариях. Одной из таких ошибок является игнорирование типа значения в параметрах. Если в базе поле хранит строку "001", а параметр передан как число 1, условие равенства может не сработать в зависимости от настроек сравнения.

Еще одна распространенная проблема — «раздувание» условия ГДЕ избыточными проверками. Например, проверка ПометкаУдаления = ЛОЖЬ часто излишня, если в запросе не используется механизм ИГНОРИРОВАНИЕ ПУСТЫХ ТАБЛИЦ или если выборка идет из регистра, где удаленные записи физически отсутствуют. Лишние условия усложняют чтение кода и могут запутать оптимизатор запросов.

⚠️ Внимание: Интерфейс и внутренние механизмы оптимизации платформы 1С могут изменяться в новых версиях. Всегда проверяйте актуальность рекомендаций по оптимизации в официальной документации к конкретной версии платформы, которую вы используете.

Также стоит упомянуть ошибку логического порядка. Разработчики часто пишут сложные условия ИЛИ, не задумываясь, что одно из простых условий могло бы отсечь 90% записей. Размещение таких условий в начале блока ГДЕ (насколько это позволяет синтаксис и логика) может ускорить выборку, хотя современный оптимизатор СУБД часто сам переставляет условия местами.

Миф о порядке условий

Существует миф, что порядок условий в ГДЕ критически важен для скорости. В реальности современные СУБД (PostgreSQL, MSSQL) сами определяют оптимальный порядок выполнения на основе статистики таблиц. Важнее структура условия, чем порядок следования.

Можно ли использовать вложенные запросы в условии ГДЕ?

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

В чем разница между ГДЕ и ИМЕЮЩИЕ?

Оператор ГДЕ фильтрует записи до группировки и агрегации, работая с исходными данными таблиц. Оператор ИМЕЮЩИЕ фильтрует результаты после группировки, позволяя отбирать группы по значениям агрегатных функций (например, СУММА(Количество) > 100). Использовать агрегатные функции в ГДЕ запрещено.

Как правильно сравнивать перечисления в ГДЕ?

Для сравнения с перечислениями лучше всего использовать параметр запроса, в который передано значение перечисления из кода 1С. Если необходимо жестко задать значение в тексте запроса, используйте конструкцию ЗНАЧЕНИЕ(Перечисление.ВидДвижения.Приход), но помните, что это усложняет поддержку при изменении метаданных.

Почему запрос с ГДЕ работает медленно на большой базе?

Наиболее вероятная причина — отсутствие индекса по полям, участвующим в условии, или использование функций над этими полями, что отключает индекс. Также возможно блокирование таблиц другими процессами. Проверьте план выполнения запроса и убедитесь, что используется индексный поиск, а не полное сканирование таблицы.

Можно ли использовать оператор ПОДОБНО для поиска по части слова?

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