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

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

ГДЕ в запросах 1С: как правильно фильтровать данные

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

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

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

Ниже разобраны синтаксис секции, типовые условия, работа с параметрами и виртуальными таблицами, а также ошибки, которые чаще всего встречаются на практике, и способы их избежать.

Синтаксис секции ГДЕ и базовые условия

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

ВЫБРАТЬ

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

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

ИЗ

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

ГДЕ

Номенклатура.ПометкаУдаления = ЛОЖЬ

И Номенклатура.ЭтоГруппа = ЛОЖЬ

В условиях допустимы операторы сравнения (=, <>, >, >=, <, <=), логические связки И, ИЛИ, НЕ, а также скобки для управления приоритетом. Без скобок оператор И выполняется раньше ИЛИ, что часто становится источником логических ошибок: выражение «А ИЛИ Б И В» трактуется как «А ИЛИ (Б И В)», а не как «(А ИЛИ Б) И В».

Значения перечислений и предопределённых элементов указываются через функцию ЗНАЧЕНИЕ, например ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС20). Пустые ссылки и даты сравниваются через ЗНАЧЕНИЕ с пустым значением соответствующего типа или через конструкцию вида = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка).

Сравнение с параметрами и списками значений

Параметры запроса обозначаются символом амперсанда — &ИмяПараметра. Перед выполнением запроса параметр заполняется методом Запрос.УстановитьПараметр("ИмяПараметра", Значение). Если параметр не установлен, платформа выдаст ошибку при выполнении, поэтому все параметры, встречающиеся в тексте, должны быть явно заданы.

Для отбора по нескольким значениям используется оператор В: ГДЕ Контрагент В (&СписокКонтрагентов). В параметр передаётся массив или список значений. Обратный отбор — НЕ В. Это удобнее, чем цепочка условий через ИЛИ, и обычно работает быстрее.

Для строковых полей доступен оператор ПОДОБНО с шаблоном, где % — любая последовательность символов, а _ — один символ: ГДЕ Наименование ПОДОБНО &Шаблон с параметром "%кабель%". Учтите, что поиск по ПОДОБНО с маской в начале строки не использует индекс и на больших таблицах выполняется медленно.

bsl
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Ссылка ИЗ Справочник.Контрагенты ГДЕ Наименование ПОДОБНО &Шаблон И НЕ ПометкаУдаления";
Запрос.УстановитьПараметр("Шаблон", "%" + СтрокаПоиска + "%");
Результат = Запрос.Выполнить().Выгрузить();

Отбор по иерархии, ссылкам и NULL

Для иерархических справочников предусмотрен оператор В ИЕРАРХИИ: ГДЕ Номенклатура В ИЕРАРХИИ(&Группа). Он выбирает саму группу и все вложенные элементы любого уровня вложенности. В параметр передаётся ссылка на группу или список групп. Это стандартный способ отобрать товары целого раздела каталога без рекурсивных обходов в коде.

Проверка типа составного поля выполняется через оператор ССЫЛКА: ГДЕ Документ.Контрагент ССЫЛКА Справочник.Контрагенты. Для приведения составного типа к конкретному используется ВЫРАЗИТЬ: ВЫРАЗИТЬ(Регистратор КАК Документ.РеализацияТоваровУслуг). После приведения становятся доступны реквизиты конкретного типа.

Значение NULL появляется в результатах левых соединений, когда подходящей записи не нашлось. Сравнивать NULL через «=» нельзя — результат будет неопределённым. Используйте ГДЕ Поле ЕСТЬ NULL или ЕСТЬ НЕ NULL, а в вычисляемых полях — функцию ЕСТЬNULL(Поле, ЗначениеПоУмолчанию).

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

ГДЕ и виртуальные таблицы регистров: где правильно фильтровать

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

ВЫБРАТЬ

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

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

ИЗ

РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, Склад = &Склад) КАК Остатки

ГДЕ

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

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

В секции ГДЕ при работе с виртуальными таблицами оставляйте только условия на результат — например, отсечение нулевых или отрицательных остатков, которые нельзя задать параметрами, или условия по полям соединённых таблиц.

Где размещать условие

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

Отбор по измерениям регистра (склад, организация, номенклатура) и периоду. Применяется при построении таблицы — быстро и экономно

Секция ГДЕ

Условия на итоговый результат (остаток > 0), отборы по полям соединённых таблиц, сложная логика с И/ИЛИ

Параметры + ГДЕ вместе

Стандартная схема: измерения — в параметры, проверки результата — в ГДЕ

Сложные условия: подзапросы, ВЫБОР КОГДА и соединения

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

Конструкция ВЫБОР КОГДА...ТОГДА...ИНАЧЕ...КОНЕЦ формально относится к списку выборки, но часто используется в связке с ГДЕ: сначала вычисляется признак, затем по нему фильтруется результат или группировка. Для фильтрации по агрегатным функциям (СУММА, КОЛИЧЕСТВО) после группировки применяется не ГДЕ, а секция ИМЕЮЩИЕ — например, ИМЕЮЩИЕ СУММА(Сумма) > 0.

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

Проверка результата и оптимизация запроса

Перед использованием запроса в коде проверяйте его в консоли запросов на реальных данных: убедитесь, что количество строк соответствует ожиданиям, нет дублей от лишних соединений и не потеряны записи из-за жёстких условий. Полезный приём — временно убрать часть условий и посмотреть, какие строки отсекаются каждым из них.

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

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

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

Как проверить корректность отбора

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

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

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

Строк заметно больше (дубли от соединений) или меньше (лишнее условие)

Строки с NULL после левого соединения
Норма

Присутствуют, если соединение левое и условий на правую таблицу нет

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

Строки пропали — условие в ГДЕ превратило соединение во внутреннее

Время выполнения на рабочей базе
Норма

Запрос отрабатывает за приемлемое время без роста при увеличении данных

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

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

FAQ: частые вопросы о ГДЕ в запросах 1С

Чем ГДЕ отличается от ИМЕЮЩИЕ?

ГДЕ фильтрует строки источников до группировки и не может содержать агрегатные функции. ИМЕЮЩИЕ применяется после СГРУППИРОВАТЬ ПО и работает с результатами СУММА, КОЛИЧЕСТВО и других агрегатов. Если нужно оставить только группы с суммой больше заданной — используйте ИМЕЮЩИЕ.

Почему условие «Поле = NULL» не работает?

В языке запросов NULL не равен ничему, включая сам себя, поэтому сравнение через «=» всегда даёт неопределённый результат. Проверяйте через «Поле ЕСТЬ NULL» или «Поле ЕСТЬ НЕ NULL», а для замены NULL на значение используйте функцию ЕСТЬNULL().

Как отобрать документы за произвольный период?

Передайте две даты параметрами и запишите условие вида «Документ.Дата МЕЖДУ &НачалоПериода И &КонецПериода». Учтите, что дата без времени означает начало дня, поэтому конец периода обычно задают функцией КонецДня() или добавляют время 23:59:59.

Можно ли использовать ГДЕ с таблицей значений?

Да: таблица значений передаётся параметром и помещается во временную таблицу (ВЫБРАТЬ ... ПОМЕСТИТЬ ВТ ИЗ &Таблица), после чего к ней применяются любые условия ГДЕ и соединения. Это стандартный способ отбора по списку, сформированному в коде.

Почему запрос с отбором по регистру работает медленно, хотя условие в ГДЕ?

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

Итог

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

Секция ГДЕ отбирает строки запроса по логическим условиям: сравнения, В, В ИЕРАРХИИ, ПОДОБНО, ЕСТЬ NULL. Для виртуальных таблиц регистров отборы по измерениям передавайте в параметры таблицы, а не в ГДЕ. Проверяйте логику скобками, следите за NULL в соединениях и тестируйте запрос в консоли до внедрения в код.