Разработка и Конфигурация · 10 мин
ГДЕ в запросах 1С: как правильно фильтровать данные
Как использовать оператор ГДЕ в запросах 1С: синтаксис, условия сравнения, В ИЕРАРХИИ, ВЫБОР КОГДА, виртуальные таблицы, типичные ошибки и оптимизация.
Оператор ГДЕ — основной инструмент фильтрации данных в языке запросов 1С. Он отсекает лишние строки ещё на уровне выборки, поэтому правильно написанное условие напрямую влияет и на корректность результата, и на скорость выполнения запроса. Ошибки в секции ГДЕ — одна из самых частых причин «пустых» отчётов, дублей и медленной работы конфигурации.
В языке запросов 1С секция ГДЕ следует после указания источников данных (ИЗ) и соединений и позволяет сочетать условия через логические операторы И, ИЛИ, НЕ, сравнивать поля с параметрами, проверять вхождение в списки и иерархию, работать с NULL. Синтаксис во многом похож на SQL, но имеет важные особенности: русские ключевые слова, специфические конструкции вроде ССЫЛКА и ВЫРАЗИТЬ, а также тесную связь с виртуальными таблицами регистров.
Ниже разобраны синтаксис секции, типовые условия, работа с параметрами и виртуальными таблицами, а также ошибки, которые чаще всего встречаются на практике, и способы их избежать.
Синтаксис секции ГДЕ и базовые условия
Минимальная структура запроса с отбором выглядит так: после ключевого слова ИЗ указывается таблица с псевдонимом, затем секция ГДЕ с условием. Условия записываются в виде логических выражений, которые должны возвращать истину или ложь для каждой строки.
ВЫБРАТЬ
Номенклатура.Ссылка,
Номенклатура.Наименование
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
Номенклатура.ПометкаУдаления = ЛОЖЬ
И Номенклатура.ЭтоГруппа = ЛОЖЬ
В условиях допустимы операторы сравнения (=, <>, >, >=, <, <=), логические связки И, ИЛИ, НЕ, а также скобки для управления приоритетом. Без скобок оператор И выполняется раньше ИЛИ, что часто становится источником логических ошибок: выражение «А ИЛИ Б И В» трактуется как «А ИЛИ (Б И В)», а не как «(А ИЛИ Б) И В».
Значения перечислений и предопределённых элементов указываются через функцию ЗНАЧЕНИЕ, например ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС20). Пустые ссылки и даты сравниваются через ЗНАЧЕНИЕ с пустым значением соответствующего типа или через конструкцию вида = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка).
Сравнение с параметрами и списками значений
Параметры запроса обозначаются символом амперсанда — &ИмяПараметра. Перед выполнением запроса параметр заполняется методом Запрос.УстановитьПараметр("ИмяПараметра", Значение). Если параметр не установлен, платформа выдаст ошибку при выполнении, поэтому все параметры, встречающиеся в тексте, должны быть явно заданы.
Для отбора по нескольким значениям используется оператор В: ГДЕ Контрагент В (&СписокКонтрагентов). В параметр передаётся массив или список значений. Обратный отбор — НЕ В. Это удобнее, чем цепочка условий через ИЛИ, и обычно работает быстрее.
Для строковых полей доступен оператор ПОДОБНО с шаблоном, где % — любая последовательность символов, а _ — один символ: ГДЕ Наименование ПОДОБНО &Шаблон с параметром "%кабель%". Учтите, что поиск по ПОДОБНО с маской в начале строки не использует индекс и на больших таблицах выполняется медленно.
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Ссылка ИЗ Справочник.Контрагенты ГДЕ Наименование ПОДОБНО &Шаблон И НЕ ПометкаУдаления";
Запрос.УстановитьПараметр("Шаблон", "%" + СтрокаПоиска + "%");
Результат = Запрос.Выполнить().Выгрузить();Отбор по иерархии, ссылкам и NULL
Для иерархических справочников предусмотрен оператор В ИЕРАРХИИ: ГДЕ Номенклатура В ИЕРАРХИИ(&Группа). Он выбирает саму группу и все вложенные элементы любого уровня вложенности. В параметр передаётся ссылка на группу или список групп. Это стандартный способ отобрать товары целого раздела каталога без рекурсивных обходов в коде.
Проверка типа составного поля выполняется через оператор ССЫЛКА: ГДЕ Документ.Контрагент ССЫЛКА Справочник.Контрагенты. Для приведения составного типа к конкретному используется ВЫРАЗИТЬ: ВЫРАЗИТЬ(Регистратор КАК Документ.РеализацияТоваровУслуг). После приведения становятся доступны реквизиты конкретного типа.
Значение NULL появляется в результатах левых соединений, когда подходящей записи не нашлось. Сравнивать NULL через «=» нельзя — результат будет неопределённым. Используйте ГДЕ Поле ЕСТЬ NULL или ЕСТЬ НЕ NULL, а в вычисляемых полях — функцию ЕСТЬNULL(Поле, ЗначениеПоУмолчанию).
ГДЕ и виртуальные таблицы регистров: где правильно фильтровать
Ключевой нюанс языка запросов 1С: для виртуальных таблиц регистров (Остатки, Обороты, СрезПоследних, СрезПервых) условия следует передавать в параметры самой виртуальной таблицы, а не в секцию ГДЕ. Параметры указываются в круглых скобках после имени таблицы.
ВЫБРАТЬ
Остатки.Номенклатура,
Остатки.КоличествоОстаток
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, Склад = &Склад) КАК Остатки
ГДЕ
Остатки.КоличествоОстаток > 0
Разница принципиальна: условие в параметрах виртуальной таблицы применяется при её построении, и платформа сразу отбирает только нужные измерения. Условие в ГДЕ применяется уже к готовому результату виртуальной таблицы, то есть сначала будут рассчитаны остатки по всем складам, а потом лишние отброшены. На крупных базах это разница между секундами и минутами выполнения.
В секции ГДЕ при работе с виртуальными таблицами оставляйте только условия на результат — например, отсечение нулевых или отрицательных остатков, которые нельзя задать параметрами, или условия по полям соединённых таблиц.
Где размещать условие
Отбор по измерениям регистра (склад, организация, номенклатура) и периоду. Применяется при построении таблицы — быстро и экономно
Условия на итоговый результат (остаток > 0), отборы по полям соединённых таблиц, сложная логика с И/ИЛИ
Стандартная схема: измерения — в параметры, проверки результата — в ГДЕ
Сложные условия: подзапросы, ВЫБОР КОГДА и соединения
В секции ГДЕ допустимы вложенные запросы через оператор В: ГДЕ Контрагент В (ВЫБРАТЬ Контрагент ИЗ РегистрСведений.Должники). Это позволяет отбирать документы по признаку, вычисляемому из другого источника. Для читаемости и повторного использования такие подзапросы часто выносят во временные таблицы через конструкцию ПОМЕСТИТЬ.
Конструкция ВЫБОР КОГДА...ТОГДА...ИНАЧЕ...КОНЕЦ формально относится к списку выборки, но часто используется в связке с ГДЕ: сначала вычисляется признак, затем по нему фильтруется результат или группировка. Для фильтрации по агрегатным функциям (СУММА, КОЛИЧЕСТВО) после группировки применяется не ГДЕ, а секция ИМЕЮЩИЕ — например, ИМЕЮЩИЕ СУММА(Сумма) > 0.
При соединении таблиц помните: условие, записанное в ГДЕ к полю правой таблицы левого соединения, фактически превращает его во внутреннее — строки без пары отфильтруются. Если нужно сохранить все строки левой таблицы, переносите условие в секцию ПО самого соединения.
Проверка результата и оптимизация запроса
Перед использованием запроса в коде проверяйте его в консоли запросов на реальных данных: убедитесь, что количество строк соответствует ожиданиям, нет дублей от лишних соединений и не потеряны записи из-за жёстких условий. Полезный приём — временно убрать часть условий и посмотреть, какие строки отсекаются каждым из них.
На производительность влияют: отбор по индексированным полям (по умолчанию индексируются ссылка, код, дата, номер, измерения регистров), отказ от ПОДОБНО с ведущей маской, перенос условий в параметры виртуальных таблиц и минимум соединений. Поле с признаком индексирования можно проверить в конфигураторе в свойствах реквизита («Индексировать»).
Если запрос тормозит, начните с замера: выполните его по частям (сначала только виртуальная таблица, потом с соединениями) и найдите, какой фрагмент даёт основную задержку. Чаще всего проблема — соединение с виртуальной таблицей без параметров или отбор по неиндексированному реквизиту большого справочника.
Как проверить корректность отбора
Совпадает с контрольной выборкой в интерфейсе (список с тем же отбором)
Строк заметно больше (дубли от соединений) или меньше (лишнее условие)
Присутствуют, если соединение левое и условий на правую таблицу нет
Строки пропали — условие в ГДЕ превратило соединение во внутреннее
Запрос отрабатывает за приемлемое время без роста при увеличении данных
Резкое замедление — проверьте параметры виртуальных таблиц и индексы
FAQ: частые вопросы о ГДЕ в запросах 1С
Чем ГДЕ отличается от ИМЕЮЩИЕ?
ГДЕ фильтрует строки источников до группировки и не может содержать агрегатные функции. ИМЕЮЩИЕ применяется после СГРУППИРОВАТЬ ПО и работает с результатами СУММА, КОЛИЧЕСТВО и других агрегатов. Если нужно оставить только группы с суммой больше заданной — используйте ИМЕЮЩИЕ.
Почему условие «Поле = NULL» не работает?
В языке запросов NULL не равен ничему, включая сам себя, поэтому сравнение через «=» всегда даёт неопределённый результат. Проверяйте через «Поле ЕСТЬ NULL» или «Поле ЕСТЬ НЕ NULL», а для замены NULL на значение используйте функцию ЕСТЬNULL().
Как отобрать документы за произвольный период?
Передайте две даты параметрами и запишите условие вида «Документ.Дата МЕЖДУ &НачалоПериода И &КонецПериода». Учтите, что дата без времени означает начало дня, поэтому конец периода обычно задают функцией КонецДня() или добавляют время 23:59:59.
Можно ли использовать ГДЕ с таблицей значений?
Да: таблица значений передаётся параметром и помещается во временную таблицу (ВЫБРАТЬ ... ПОМЕСТИТЬ ВТ ИЗ &Таблица), после чего к ней применяются любые условия ГДЕ и соединения. Это стандартный способ отбора по списку, сформированному в коде.
Почему запрос с отбором по регистру работает медленно, хотя условие в ГДЕ?
Скорее всего, условие по измерениям регистра записано в ГДЕ вместо параметров виртуальной таблицы. Платформа сначала строит всю виртуальную таблицу, а потом фильтрует её. Перенесите отбор по измерениям и периоду в скобки после имени виртуальной таблицы.
Что важно запомнить
Секция ГДЕ отбирает строки запроса по логическим условиям: сравнения, В, В ИЕРАРХИИ, ПОДОБНО, ЕСТЬ NULL. Для виртуальных таблиц регистров отборы по измерениям передавайте в параметры таблицы, а не в ГДЕ. Проверяйте логику скобками, следите за NULL в соединениях и тестируйте запрос в консоли до внедрения в код.