К статье
Практический материал

Разработка и Конфигурация · 15 мин

Как работает условие ГДЕ в запросах 1С

Разбираем, как работает условие ГДЕ в языке запросов 1С: синтаксис, операторы сравнения, ВЫБОР КОГДА, виртуальные таблицы, типичные ошибки и проверка результата.

Условие ГДЕ (в английском синтаксисе — WHERE) — основной инструмент фильтрации данных в языке запросов 1С. Оно определяет, какие строки из выборки попадут в результат, а какие будут отброшены ещё на этапе выполнения запроса. Правильно построенное условие сокращает объём обрабатываемых данных и напрямую влияет на скорость работы отчётов, обработок и проведения документов.

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

Материал ориентирован на разработчиков и внедренцев, которые пишут запросы в конфигураторе, консоли запросов или коде модулей. Разберём синтаксис, логические операторы, работу с параметрами, особенности виртуальных таблиц и способы проверить, что условие отрабатывает именно так, как задумано.

Синтаксис условия ГДЕ и порядок его вычисления

Секция ГДЕ размещается после перечисления источников данных (секция ИЗ с соединениями) и до группировки, итогов и упорядочивания. Минимальный пример:

ВЫБРАТЬ

Номенклатура.Ссылка КАК Товар,

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

ИЗ

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

ГДЕ

НЕ Номенклатура.ПометкаУдаления

Условие вычисляется для каждой строки, которую вернул бы запрос без фильтра. Если выражение истинно — строка попадает в результат. Важно понимать порядок: сначала платформа формирует соединение таблиц, затем применяет ГДЕ, потом группировку и итоги. Поэтому условие на поле, которое обнуляется при левом соединении, фактически превращает левое соединение во внутреннее — это частая причина «пропавших» строк.

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

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

В условиях доступны стандартные операторы сравнения: =, <>, >, <, >=, <=. Для строк, дат и ссылок сравнение выполняется по правилам упорядочивания типа. Помимо этого есть специальные предикаты:

  • В (&Список) — проверка вхождения значения в список, массив или результат вложенного запроса;
  • МЕЖДУ ... И ... — проверка попадания в диапазон, границы включаются;
  • ПОДОБНО "%шаблон%" — поиск по шаблону строки, где % — любое количество символов, _ — один символ;
  • ЕСТЬ NULL и НЕ ... ЕСТЬ NULL — проверка на NULL, равенство с NULL через = не работает;
  • В ИЕРАРХИИ — проверка принадлежности элемента группе с учётом вложенности.

Логические связки: И, ИЛИ, НЕ. Приоритет стандартный: сначала НЕ, затем И, затем ИЛИ. Смешивая И и ИЛИ, всегда расставляйте скобки явно — без них условие вида А И Б ИЛИ В вычисляется как (А И Б) ИЛИ В, что часто не совпадает с намерением разработчика.

Типичные ошибки в условиях
01
Сравнение с NULL через знак равенства: условие Поле = NULL всегда ложно, в результат попадает ноль строк. Используйте Поле ЕСТЬ NULL.
02
Смешение И и ИЛИ без скобок: логика фильтра меняется, в выборку попадают лишние строки.
03
Фильтр по полю присоединённой таблицы в ГДЕ при левом соединении: строки с NULL отбрасываются, соединение фактически становится внутренним.
04
Сравнение строки с числом или даты со строкой: неявное приведение типов даёт пустой результат без сообщения об ошибке.

Условия с параметрами запроса

Параметры обозначаются символом & и передаются в запрос через метод УстановитьПараметр() объекта Запрос. Это основной способ сделать запрос универсальным:

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

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

"ВЫБРАТЬ

| Продажи.Номенклатура КАК Товар,

| СУММА(Продажи.Количество) КАК Количество

|ИЗ

| РегистрНакопления.Продажи КАК Продажи

|ГДЕ

| Продажи.Период МЕЖДУ &НачалоПериода И &КонецПериода

| И Продажи.Номенклатура В (&СписокТоваров)

|СГРУППИРОВАТЬ ПО

| Продажи.Номенклатура";

Запрос.УстановитьПараметр("НачалоПериода", НачалоМесяца(ТекущаяДатаСеанса()));

Запрос.УстановитьПараметр("КонецПериода", КонецМесяца(ТекущаяДатаСеанса()));

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

Несколько практических правил. В параметр для оператора В можно передавать массив или список значений — платформа сама развернёт его в перечисление. Если параметр не установлен, при выполнении возникнет ошибка, поэтому все параметры следует задавать явно, даже если значение пустое. Для «необязательных» фильтров применяют приём с проверкой на пустое значение: ГДЕ (&Отбор = НЕОПРЕДЕЛЕНО ИЛИ Поле = &Отбор) — либо формируют текст запроса динамически, добавляя условие только когда отбор задан.

Фильтрация в виртуальных таблицах регистров

Отдельный и самый важный сценарий — условия для виртуальных таблиц регистров: остатков, оборотов, срезов первых и последних. У таких таблиц есть собственные параметры, которые задаются в круглых скобках после имени таблицы, а не в секции ГДЕ:

ВЫБРАТЬ

Остатки.Номенклатура КАК Товар,

Остатки.КоличествоОстаток КАК Остаток

ИЗ

РегистрНакопления.ТоварыНаСкладах.Остатки(

&ДатаОстатков,

Склад = &Склад

И Номенклатура В (&Товары)) КАК Остатки

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

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

Где задавать фильтр

Параметры виртуальной таблицы

Подходит для отборов по измерениям и периоду. Выполняется быстрее, так как ограничивает расчёт итогов. Ограничение: только простые сравнения.

Секция ГДЕ

Подходит для условий по ресурсам, вычисляемым полям, функциям и связям с другими таблицами. Применяется к уже построенной выборке, поэтому медленнее на больших объёмах.

Вычисляемые условия: ВЫБОР КОГДА и функции в ГДЕ

Конструкция ВЫБОР КОГДА ... ТОГДА ... ИНАЧЕ ... КОНЕЦ — аналог CASE — чаще используется в списке выборки, но может участвовать и в условии. Например, отобрать строки, где расчётный признак принимает нужное значение:

ГДЕ

ВЫБОР

КОГДА Продажи.Сумма > 100000

ТОГДА ИСТИНА

ИНАЧЕ ЛОЖЬ

КОНЕЦ

Такой подход оправдан, когда логика ветвления сложная и дублировать её в нескольких условиях через ИЛИ неудобно. Однако простые случаи читаются лучше в виде обычного сравнения: ГДЕ Продажи.Сумма > 100000.

В условиях допустимы функции языка запросов: ПОДСТРОКА, ДЛИНАСТРОКИ, ГОД, МЕСЯЦ, НАЧАЛОПЕРИОДА, КОНЕЦПЕРИОДА, ДАТАВРЕМЯ, ЗНАЧЕНИЕ для предопределённых элементов и перечислений. Имейте в виду: функция, применённая к полю таблицы, как правило, мешает оптимизатору использовать индекс, и фильтрация превращается в полный перебор. Если возможно, преобразуйте условие так, чтобы функция применялась к параметру, а не к полю: вместо ГОД(Документ.Дата) = 2026 — Документ.Дата МЕЖДУ &НачалоГода И &КонецГода.

Если запрос с условием по дате внезапно стал медленным, проверьте, не обёрнуто ли поле даты в функцию. Перенос вычисления границ периода в параметры обычно возвращает нормальную скорость без переписывания всего запроса.
ПЗ
Практическое замечание

Условия с вложенными запросами и соединениями

Оператор В принимает не только список, но и вложенный запрос. Типовой сценарий — отобрать документы, у которых есть строки с определённым товаром:

ВЫБРАТЬ

Реализация.Ссылка КАК Документ

ИЗ

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

ГДЕ

Реализация.Ссылка В

(ВЫБРАТЬ РАЗЛИЧНЫЕ

Товары.Ссылка

ИЗ

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

ГДЕ

Товары.Номенклатура = &Товар)

Альтернатива — соединение с табличной частью и группировка, но вложенный запрос с В читается проще и не размножает строки. При использовании НЕ В будьте осторожны: если вложенный запрос вернёт NULL, условие может повести себя неочевидно. Для отрицательных проверок надёжнее связка левого соединения с условием Таблица.Поле ЕСТЬ NULL.

Помните и про ограничение: условие в секции ГДЕ соединяемых таблиц влияет на итоговый результат иначе, чем условие в секции ПО соединения. Условие в ПО фильтрует только присоединяемую таблицу, сохраняя строки основной; условие в ГДЕ отбрасывает строки целиком. Для левых соединений фильтры по правой таблице почти всегда следует писать в ПО.

Маршрут решения

Как выбрать место для условия

Нужно ограничить расчёт итогов виртуальной таблицы по измерениям или периодуЗадайте отбор в параметрах виртуальной таблицы в круглых скобках
Фильтр по полю правой таблицы при левом соединении, строки основной таблицы терять нельзяПоместите условие в секцию ПО соединения
Нужно отбросить строки результата по любому выражению, включая функции и ресурсыИспользуйте секцию ГДЕ
Проверяется наличие связанных записей без нужды выводить их поляИспользуйте предикат В с вложенным запросом

Проверка результата и отладка условий

Главный инструмент отладки — консоль запросов: она позволяет выполнить запрос с реальными параметрами и увидеть выборку до переноса кода в модуль. Порядок проверки условия, которое «не срабатывает»:

  1. Выполните запрос без секции ГДЕ и убедитесь, что искомые строки вообще существуют в источнике.
  2. Добавляйте предикаты по одному, после каждого проверяя, не исчезли ли нужные строки.
  3. Выведите в список выборки само условное выражение как поле — станет видно, для каких строк оно ложно и почему.
  4. Проверьте типы сравниваемых значений: выведите ТИПЗНАЧЕНИЯ(Поле) и тип параметра.
  5. Для условий с NULL временно замените поле на ЕСТЬNULL(Поле, "пусто"), чтобы увидеть фактическое содержимое.

Отдельно проверяйте граничные случаи: пустой параметр-список (условие В (&Список) с пустым массивом не вернёт ни одной строки), даты без времени, разные регистры строк в условии ПОДОБНО. Если запрос используется в отчёте на СКД, помните, что отборы настроек компоновки добавляются к тексту запроса автоматически и могут конфликтовать с условиями в ГДЕ.

Контрольные точки

Как проверить результат

Количество строк результата
Норма

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

Тревожный признак

Результат пустой, хотя данные в источнике есть

Типы сравниваемых значений
Норма

Поле и параметр одного типа или типы совместимы

Тревожный признак

Сравниваются строка с числом, ссылка со строкой

Условие с левым соединением
Норма

Строки основной таблицы без связанных данных сохраняются

Тревожный признак

Строки без пары пропали — фильтр правой таблицы попал в ГДЕ

Скорость выполнения на рабочей базе
Норма

Запрос отрабатывает за приемлемое время

Тревожный признак

Резкая деградация при росте данных — фильтр не в параметрах виртуальной таблицы

Порядок написания условия ГДЕ
  1. 1
    Определите, какие строки должны попасть в результат, и сформулируйте это словами
  2. 2
    Разделите условия: что можно отнести в параметры виртуальной таблицы или секцию ПО соединения
  3. 3
    Запишите оставшиеся предикаты в ГДЕ, расставив скобки при смешении И и ИЛИ
  4. 4
    Замените конкретные значения на параметры и установите их в коде
  5. 5
    Выполните запрос в консоли, проверьте граничные случаи: NULL, пустой список, края диапазона дат

Ограничения и частые заблуждения

Язык запросов 1С не поддерживает произвольные выражения встроенного языка внутри условий: нельзя вызвать метод объекта или функцию общего модуля. Если логику фильтра невозможно выразить средствами запроса, её выносят либо в предварительное заполнение временной таблицы, либо в постобработку выборки в коде.

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

Ещё одно ограничение касается пакетных запросов: условие в одном запросе пакета не видит результатов другого, если они не связаны через временную таблицу. Для многошаговой фильтрации помещайте промежуточную выборку во временную таблицу (ПОМЕСТИТЬ) и ссылайтесь на неё в следующем запросе.

Частые вопросы

Чем ГДЕ отличается от ИМЕЮЩИЕ в запросе 1С?

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

Почему условие Поле = &Параметр не находит строки, хотя значение совпадает?

Чаще всего причина в несовпадении типов: в параметр передана строка, а поле имеет тип ссылки, или наоборот. Проверьте тип параметра в отладчике и тип поля через ТИПЗНАЧЕНИЯ. Вторая причина — лишние пробелы или неразрывные пробелы в строковых значениях.

Как сделать необязательный отбор, который работает только при заполненном параметре?

Используйте конструкцию вида ГДЕ (&Отбор = НЕОПРЕДЕЛЕНО ИЛИ Поле = &Отбор) и передавайте НЕОПРЕДЕЛЕНО, когда отбор не нужен. Альтернатива — динамическое формирование текста запроса, когда условие добавляется в строку только при заполненном значении.

Можно ли использовать ВЫБОР внутри условия ГДЕ?

Да, конструкция ВЫБОР КОГДА допустима в условии, если её результат — булево или сравниваемое значение. Но для простых случаев обычное сравнение читается легче; ВЫБОР оправдан при многоуровневом ветвлении логики.

Почему условие по полю присоединённой таблицы «теряет» строки при левом соединении?

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

Что быстрее: условие в ГДЕ или в параметрах виртуальной таблицы?

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

Итог

Что важно запомнить

ГДЕ фильтрует строки результата по логическому выражению и вычисляется после соединений, но до группировки. Отборы по измерениям виртуальных таблиц выносите в их параметры, условия по правой таблице левого соединения — в секцию ПО, NULL проверяйте через ЕСТЬ NULL, а смешение И и ИЛИ всегда уточняйте скобками. Проверяйте условия пошагово в консоли запросов на копии базы.