Разработка и Конфигурация · 15 мин
Как работает условие ГДЕ в запросах 1С
Разбираем, как работает условие ГДЕ в языке запросов 1С: синтаксис, операторы сравнения, ВЫБОР КОГДА, виртуальные таблицы, типичные ошибки и проверка результата.
Условие ГДЕ (в английском синтаксисе — WHERE) — основной инструмент фильтрации данных в языке запросов 1С. Оно определяет, какие строки из выборки попадут в результат, а какие будут отброшены ещё на этапе выполнения запроса. Правильно построенное условие сокращает объём обрабатываемых данных и напрямую влияет на скорость работы отчётов, обработок и проведения документов.
Ключевая особенность языка запросов 1С: это декларативный язык, близкий к SQL, но со своими ограничениями и расширениями. Условие ГДЕ здесь работает не только с полями таблиц, но и с параметрами запроса, функциями, вложенными запросами и виртуальными таблицами. Понимание порядка вычисления условий помогает избежать типичных ошибок — от пустых выборок до неявного преобразования типов.
Материал ориентирован на разработчиков и внедренцев, которые пишут запросы в конфигураторе, консоли запросов или коде модулей. Разберём синтаксис, логические операторы, работу с параметрами, особенности виртуальных таблиц и способы проверить, что условие отрабатывает именно так, как задумано.
Синтаксис условия ГДЕ и порядок его вычисления
Секция ГДЕ размещается после перечисления источников данных (секция ИЗ с соединениями) и до группировки, итогов и упорядочивания. Минимальный пример:
ВЫБРАТЬ
Номенклатура.Ссылка КАК Товар,
Номенклатура.Наименование КАК Наименование
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
НЕ Номенклатура.ПометкаУдаления
Условие вычисляется для каждой строки, которую вернул бы запрос без фильтра. Если выражение истинно — строка попадает в результат. Важно понимать порядок: сначала платформа формирует соединение таблиц, затем применяет ГДЕ, потом группировку и итоги. Поэтому условие на поле, которое обнуляется при левом соединении, фактически превращает левое соединение во внутреннее — это частая причина «пропавших» строк.
В условии можно использовать поля источников, параметры запроса, литералы (числа, строки, даты, булево), арифметические выражения и встроенные функции языка запросов. Нельзя напрямую обращаться к реквизитам через точку от ссылки без явного указания таблицы — псевдоним источника обязателен.
Операторы сравнения и логические связки
В условиях доступны стандартные операторы сравнения: =, <>, >, <, >=, <=. Для строк, дат и ссылок сравнение выполняется по правилам упорядочивания типа. Помимо этого есть специальные предикаты:
В (&Список)— проверка вхождения значения в список, массив или результат вложенного запроса;МЕЖДУ ... И ...— проверка попадания в диапазон, границы включаются;ПОДОБНО "%шаблон%"— поиск по шаблону строки, где%— любое количество символов,_— один символ;ЕСТЬ NULLиНЕ ... ЕСТЬ NULL— проверка на NULL, равенство с NULL через=не работает;В ИЕРАРХИИ— проверка принадлежности элемента группе с учётом вложенности.
Логические связки: И, ИЛИ, НЕ. Приоритет стандартный: сначала НЕ, затем И, затем ИЛИ. Смешивая И и ИЛИ, всегда расставляйте скобки явно — без них условие вида А И Б ИЛИ В вычисляется как (А И Б) ИЛИ В, что часто не совпадает с намерением разработчика.
Условия с параметрами запроса
Параметры обозначаются символом & и передаются в запрос через метод УстановитьПараметр() объекта Запрос. Это основной способ сделать запрос универсальным:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Продажи.Номенклатура КАК Товар,
| СУММА(Продажи.Количество) КАК Количество
|ИЗ
| РегистрНакопления.Продажи КАК Продажи
|ГДЕ
| Продажи.Период МЕЖДУ &НачалоПериода И &КонецПериода
| И Продажи.Номенклатура В (&СписокТоваров)
|СГРУППИРОВАТЬ ПО
| Продажи.Номенклатура";
Запрос.УстановитьПараметр("НачалоПериода", НачалоМесяца(ТекущаяДатаСеанса()));
Запрос.УстановитьПараметр("КонецПериода", КонецМесяца(ТекущаяДатаСеанса()));
Запрос.УстановитьПараметр("СписокТоваров", МассивТоваров);
Несколько практических правил. В параметр для оператора В можно передавать массив или список значений — платформа сама развернёт его в перечисление. Если параметр не установлен, при выполнении возникнет ошибка, поэтому все параметры следует задавать явно, даже если значение пустое. Для «необязательных» фильтров применяют приём с проверкой на пустое значение: ГДЕ (&Отбор = НЕОПРЕДЕЛЕНО ИЛИ Поле = &Отбор) — либо формируют текст запроса динамически, добавляя условие только когда отбор задан.
Фильтрация в виртуальных таблицах регистров
Отдельный и самый важный сценарий — условия для виртуальных таблиц регистров: остатков, оборотов, срезов первых и последних. У таких таблиц есть собственные параметры, которые задаются в круглых скобках после имени таблицы, а не в секции ГДЕ:
ВЫБРАТЬ
Остатки.Номенклатура КАК Товар,
Остатки.КоличествоОстаток КАК Остаток
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки(
&ДатаОстатков,
Склад = &Склад
И Номенклатура В (&Товары)) КАК Остатки
Разница принципиальна. Параметр виртуальной таблицы применяется на этапе её построения: платформа сразу отбирает только нужные записи из итогов. Условие в ГДЕ применяется уже к готовой выборке виртуальной таблицы — сначала будут рассчитаны остатки по всем товарам и складам, и лишь потом лишние строки отброшены. На крупных базах разница во времени выполнения может достигать десятков раз.
Не всякое условие можно перенести в параметры виртуальной таблицы: там допустимы только сравнения полей таблицы с параметрами, константами и простыми выражениями. Сложные конструкции с функциями или полями других таблиц останутся в ГДЕ. Признак правильного решения — условие по измерениям регистра (склад, товар, организация) вынесено в параметры, а постобработка (например, отсечение нулевых остатков) — в ГДЕ.
Где задавать фильтр
Подходит для отборов по измерениям и периоду. Выполняется быстрее, так как ограничивает расчёт итогов. Ограничение: только простые сравнения.
Подходит для условий по ресурсам, вычисляемым полям, функциям и связям с другими таблицами. Применяется к уже построенной выборке, поэтому медленнее на больших объёмах.
Вычисляемые условия: ВЫБОР КОГДА и функции в ГДЕ
Конструкция ВЫБОР КОГДА ... ТОГДА ... ИНАЧЕ ... КОНЕЦ — аналог CASE — чаще используется в списке выборки, но может участвовать и в условии. Например, отобрать строки, где расчётный признак принимает нужное значение:
ГДЕ
ВЫБОР
КОГДА Продажи.Сумма > 100000
ТОГДА ИСТИНА
ИНАЧЕ ЛОЖЬ
КОНЕЦ
Такой подход оправдан, когда логика ветвления сложная и дублировать её в нескольких условиях через ИЛИ неудобно. Однако простые случаи читаются лучше в виде обычного сравнения: ГДЕ Продажи.Сумма > 100000.
В условиях допустимы функции языка запросов: ПОДСТРОКА, ДЛИНАСТРОКИ, ГОД, МЕСЯЦ, НАЧАЛОПЕРИОДА, КОНЕЦПЕРИОДА, ДАТАВРЕМЯ, ЗНАЧЕНИЕ для предопределённых элементов и перечислений. Имейте в виду: функция, применённая к полю таблицы, как правило, мешает оптимизатору использовать индекс, и фильтрация превращается в полный перебор. Если возможно, преобразуйте условие так, чтобы функция применялась к параметру, а не к полю: вместо ГОД(Документ.Дата) = 2026 — Документ.Дата МЕЖДУ &НачалоГода И &КонецГода.
Если запрос с условием по дате внезапно стал медленным, проверьте, не обёрнуто ли поле даты в функцию. Перенос вычисления границ периода в параметры обычно возвращает нормальную скорость без переписывания всего запроса.
Условия с вложенными запросами и соединениями
Оператор В принимает не только список, но и вложенный запрос. Типовой сценарий — отобрать документы, у которых есть строки с определённым товаром:
ВЫБРАТЬ
Реализация.Ссылка КАК Документ
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
Реализация.Ссылка В
(ВЫБРАТЬ РАЗЛИЧНЫЕ
Товары.Ссылка
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК Товары
ГДЕ
Товары.Номенклатура = &Товар)
Альтернатива — соединение с табличной частью и группировка, но вложенный запрос с В читается проще и не размножает строки. При использовании НЕ В будьте осторожны: если вложенный запрос вернёт NULL, условие может повести себя неочевидно. Для отрицательных проверок надёжнее связка левого соединения с условием Таблица.Поле ЕСТЬ NULL.
Помните и про ограничение: условие в секции ГДЕ соединяемых таблиц влияет на итоговый результат иначе, чем условие в секции ПО соединения. Условие в ПО фильтрует только присоединяемую таблицу, сохраняя строки основной; условие в ГДЕ отбрасывает строки целиком. Для левых соединений фильтры по правой таблице почти всегда следует писать в ПО.
Как выбрать место для условия
Проверка результата и отладка условий
Главный инструмент отладки — консоль запросов: она позволяет выполнить запрос с реальными параметрами и увидеть выборку до переноса кода в модуль. Порядок проверки условия, которое «не срабатывает»:
- Выполните запрос без секции
ГДЕи убедитесь, что искомые строки вообще существуют в источнике. - Добавляйте предикаты по одному, после каждого проверяя, не исчезли ли нужные строки.
- Выведите в список выборки само условное выражение как поле — станет видно, для каких строк оно ложно и почему.
- Проверьте типы сравниваемых значений: выведите
ТИПЗНАЧЕНИЯ(Поле)и тип параметра. - Для условий с NULL временно замените поле на
ЕСТЬNULL(Поле, "пусто"), чтобы увидеть фактическое содержимое.
Отдельно проверяйте граничные случаи: пустой параметр-список (условие В (&Список) с пустым массивом не вернёт ни одной строки), даты без времени, разные регистры строк в условии ПОДОБНО. Если запрос используется в отчёте на СКД, помните, что отборы настроек компоновки добавляются к тексту запроса автоматически и могут конфликтовать с условиями в ГДЕ.
Как проверить результат
Совпадает с выборкой без условия минус ожидаемо отфильтрованные строки
Результат пустой, хотя данные в источнике есть
Поле и параметр одного типа или типы совместимы
Сравниваются строка с числом, ссылка со строкой
Строки основной таблицы без связанных данных сохраняются
Строки без пары пропали — фильтр правой таблицы попал в ГДЕ
Запрос отрабатывает за приемлемое время
Резкая деградация при росте данных — фильтр не в параметрах виртуальной таблицы
- 1Определите, какие строки должны попасть в результат, и сформулируйте это словами
- 2Разделите условия: что можно отнести в параметры виртуальной таблицы или секцию ПО соединения
- 3Запишите оставшиеся предикаты в ГДЕ, расставив скобки при смешении И и ИЛИ
- 4Замените конкретные значения на параметры и установите их в коде
- 5Выполните запрос в консоли, проверьте граничные случаи: NULL, пустой список, края диапазона дат
Ограничения и частые заблуждения
Язык запросов 1С не поддерживает произвольные выражения встроенного языка внутри условий: нельзя вызвать метод объекта или функцию общего модуля. Если логику фильтра невозможно выразить средствами запроса, её выносят либо в предварительное заполнение временной таблицы, либо в постобработку выборки в коде.
Распространённое заблуждение — что ГДЕ «ускоряет» любой запрос. Условие сокращает результат, но не гарантирует использования индексов: функции над полями, сравнение разных типов, ПОДОБНО с маской в начале строки заставляют СУБД перебирать данные целиком. Оптимизация начинается с анализа плана запроса и корректной работы с виртуальными таблицами, а не с добавления новых предикатов.
Ещё одно ограничение касается пакетных запросов: условие в одном запросе пакета не видит результатов другого, если они не связаны через временную таблицу. Для многошаговой фильтрации помещайте промежуточную выборку во временную таблицу (ПОМЕСТИТЬ) и ссылайтесь на неё в следующем запросе.
Частые вопросы
Чем ГДЕ отличается от ИМЕЮЩИЕ в запросе 1С?
ГДЕ фильтрует строки до группировки, а ИМЕЮЩИЕ — уже сгруппированные данные по значениям агрегатных функций. Например, отбор товаров с суммарным количеством больше заданного пишется через ИМЕЮЩИЕ СУММА(Количество) > &Минимум, потому что до группировки итога ещё не существует.
Почему условие Поле = &Параметр не находит строки, хотя значение совпадает?
Чаще всего причина в несовпадении типов: в параметр передана строка, а поле имеет тип ссылки, или наоборот. Проверьте тип параметра в отладчике и тип поля через ТИПЗНАЧЕНИЯ. Вторая причина — лишние пробелы или неразрывные пробелы в строковых значениях.
Как сделать необязательный отбор, который работает только при заполненном параметре?
Используйте конструкцию вида ГДЕ (&Отбор = НЕОПРЕДЕЛЕНО ИЛИ Поле = &Отбор) и передавайте НЕОПРЕДЕЛЕНО, когда отбор не нужен. Альтернатива — динамическое формирование текста запроса, когда условие добавляется в строку только при заполненном значении.
Можно ли использовать ВЫБОР внутри условия ГДЕ?
Да, конструкция ВЫБОР КОГДА допустима в условии, если её результат — булево или сравниваемое значение. Но для простых случаев обычное сравнение читается легче; ВЫБОР оправдан при многоуровневом ветвлении логики.
Почему условие по полю присоединённой таблицы «теряет» строки при левом соединении?
Потому что для строк без пары поле правой таблицы равно NULL, а любое сравнение с NULL ложно. Перенесите условие в секцию ПО соединения — тогда фильтрация затронет только присоединяемые данные, а строки основной таблицы сохранятся.
Что быстрее: условие в ГДЕ или в параметрах виртуальной таблицы?
Параметры виртуальной таблицы почти всегда быстрее, потому что ограничивают объём рассчитываемых итогов ещё до формирования выборки. Условие в ГДЕ применяется к уже построенной таблице. Поэтому отборы по измерениям и периоду следует выносить в параметры, когда это позволяет синтаксис.
Что важно запомнить
ГДЕ фильтрует строки результата по логическому выражению и вычисляется после соединений, но до группировки. Отборы по измерениям виртуальных таблиц выносите в их параметры, условия по правой таблице левого соединения — в секцию ПО, NULL проверяйте через ЕСТЬ NULL, а смешение И и ИЛИ всегда уточняйте скобками. Проверяйте условия пошагово в консоли запросов на копии базы.