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

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

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

Как писать условие ГДЕ в запросе 1С 8.3: операторы сравнения, В, МЕЖДУ, ПОДОБНО, параметры, виртуальные таблицы, типичные ошибки и проверка результата.

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

Условие записывается после предложения ИЗ и перед УПОРЯДОЧИТЬ ПО или СГРУППИРОВАТЬ ПО. Внутри ГДЕ можно использовать сравнения, логические операторы И/ИЛИ/НЕ, проверки на NULL, отбор по спискам, диапазонам и шаблонам строк. Ниже разобраны все основные конструкции с примерами, которые можно сразу проверить в консоли запросов.

Отдельная тема — параметры. В типовом коде условия почти всегда строятся на параметрах (&ИмяПараметра), а не на жёстко прописанных значениях: это безопаснее, позволяет переиспользовать текст запроса и корректно работает с типами данных 1С.

Базовый синтаксис условия ГДЕ

Простейшее условие — сравнение поля со значением или параметром. Поддерживаются операторы =, <> (неравенство), >, <, >=, <=.

ВЫБРАТЬ

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

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

ИЗ

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

ГДЕ

Номенклатура.Родитель = &Группа

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

Логические операторы И, ИЛИ, НЕ комбинируют несколько проверок. Приоритет: сначала НЕ, затем И, затем ИЛИ. Чтобы не гадать с приоритетом, всегда ставьте скобки в смешанных условиях — это самая частая причина «неправильно работающего» отбора.

Поля в условии можно сравнивать между собой, а не только с константами: ГДЕ Строки.Количество > Строки.КоличествоПоДокументу. Это удобно для поиска расхождений в данных.

Параметры запроса: как передавать значения в ГДЕ

Параметр обозначается символом & перед именем. Значение присваивается перед выполнением запроса методом УстановитьПараметр:

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

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

"ВЫБРАТЬ

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

|ИЗ

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

|ГДЕ

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

| И Реализация.Контрагент = &Контрагент";

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

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

Запрос.УстановитьПараметр("Контрагент", КонтрагентСсылка);

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

Если параметр не установлен, при выполнении возникнет ошибка «Параметр не найден» — поэтому в коде с ветвлениями проверяйте, что все параметры установлены на каждом пути. В консоли запросов параметры задаются на отдельной вкладке.

Тип параметра должен совпадать с типом поля. Частая ошибка — передать строку туда, где ожидается ссылка: сравнение не выдаст ошибку, но вернёт пустой результат, и это сложно отладить.

Отбор по списку значений: оператор В

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

ГДЕ

Товары.Склад В (&СписокСкладов)

И Товары.ВидНоменклатуры В (&Вид1, &Вид2)

Параметр-массив заполняется в коде: Запрос.УстановитьПараметр("СписокСкладов", МассивСкладов);. Обратное условие — НЕ ... В (...) — исключает перечисленные значения.

Для иерархических справочников есть вариант В ИЕРАРХИИ: он отбирает элементы, находящиеся внутри указанной группы на любом уровне вложенности. Это стандартный способ отобрать товары по папке вместе со всеми подпапками.

ГДЕ

Номенклатура.Ссылка В ИЕРАРХИИ(&ГруппаТоваров)

Сравнение вариантов отбора по группе

Родитель = &Группа

Только элементы первого уровня внутри группы. Быстро, но подгруппы не попадут в выборку.

В ИЕРАРХИИ(&Группа)

Все уровни вложенности. Правильный вариант для отчётов по папке справочника, но требует обхода иерархии.

Диапазоны и строки: МЕЖДУ, ПОДОБНО, ЕСТЬ NULL

Оператор МЕЖДУ ... И ... проверяет попадание в диапазон включительно, границы входят в результат. Типичное применение — отбор документов за период. Учтите: для даты конца периода используйте КонецДня() или функцию КОНЕЦПЕРИОДА(&Дата, ДЕНЬ), иначе документы, созданные в конце дня с временем, выпадут из выборки.

Оператор ПОДОБНО ищет строки по шаблону. Символ % — любая последовательность символов, _ — ровно один символ, квадратные скобки [...] — один символ из набора.

ГДЕ

Контрагенты.Наименование ПОДОБНО &Шаблон

ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО "%" + &Фрагмент + "%"

Проверка на незаполненное значение делается через ЕСТЬ NULL / НЕ ... ЕСТЬ NULL. NULL в запросах появляется при левых соединениях и в полях составного типа. Сравнение = NULL не работает — оно всегда даёт ложь, используйте только ЕСТЬ NULL.

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

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

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

ВЫБРАТЬ

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

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

ИЗ

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

&Период,

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

И Номенклатура В ИЕРАРХИИ(&Группа)) КАК Остатки

В параметрах виртуальной таблицы первым аргументом идёт период, вторым — строка условия по измерениям. Внутри этого условия доступны те же операторы: равенство, В, В ИЕРАРХИИ, МЕЖДУ. Фильтровать по реквизитам регистра здесь нельзя — только по измерениям.

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

Порядок оптимизации медленного запроса
  1. 1
    Откройте текст запроса и найдите все обращения к виртуальным таблицам регистров.
  2. 2
    Перенесите условия по измерениям из секции ГДЕ в параметры виртуальной таблицы.
  3. 3
    Проверьте, что отбор по периоду задан первым параметром, а не сравнением поля Период в ГДЕ.
  4. 4
    Выполните запрос в консоли на копии базы и сравните время до и после изменения.
  5. 5
    Убедитесь, что результат выборки не изменился — состав строк должен совпасть.

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

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

ГДЕ

Валюты.Ссылка = ЗНАЧЕНИЕ(Справочник.Валюты.USD)

И Продажи.Дата >= НАЧАЛОПЕРИОДА(&Дата, МЕСЯЦ)

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

Для полей составного типа полезна функция ВЫРАЗИТЬ(... КАК ...): приведение типа в условии позволяет сравнивать поле с параметром конкретного типа и иногда помогает оптимизатору. Например: ГДЕ ВЫРАЗИТЬ(Регистратор КАК Документ.РеализацияТоваровУслуг) = &Документ.

Проверяйте новые условия в консоли запросов на копии рабочей базы, а не в боевой. Сначала выполните запрос без ГДЕ, посмотрите объём полной выборки, затем добавьте условие и сравните количество строк — так сразу видно, не «съедает» ли отбор лишнее.
ПЗ
Практическое замечание

Проверка результата и границы самостоятельной работы

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

Обратите внимание на дубли: если в запросе есть соединения, условие ГДЕ может отфильтровать строки, но количество удвоится из-за связи «один ко многим». Это не ошибка условия, а особенность соединения — проверяйте уникальность по ключевым полям.

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

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

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

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

Совпадает с контрольным отчётом или ожидаемым числом документов

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

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

Границы периода
Норма

Документы первой и последней секунды периода присутствуют

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

Пропадают документы конца дня — не задан КОНЕЦПЕРИОДА

Пустые значения
Норма

Записи с незаполненными полями обработаны через ЕСТЬ NULL осознанно

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

Записи с NULL молча исключены из результата

Время выполнения
Норма

Запрос на рабочем объёме выполняется быстро

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

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

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

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

ГДЕ фильтрует строки до группировки, а ИМЕЮЩИЕ — после неё и применяется к агрегатным функциям: СУММА, КОЛИЧЕСТВО, МАКСИМУМ. Например, «клиенты с суммой продаж больше миллиона» — это ИМЕЮЩИЕ СУММА(Продажи.Сумма) > 1000000. Условие по самому полю без агрегации оставляйте в ГДЕ: так запрос отбрасывает лишние строки раньше и работает быстрее.

Как отобрать записи, где поле не заполнено?

Поведение зависит от типа поля. Для ссылочных полей пустое значение — это пустая ссылка: ГДЕ Поле = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка). Для строк — сравнение с пустой строкой. Для полей, полученных соединением, — проверка ЕСТЬ NULL. Универсального «пусто» нет, поэтому сначала выясните тип поля.

Почему условие с параметром возвращает пустой результат без ошибки?

Чаще всего тип параметра не совпадает с типом поля: передана строка вместо ссылки, число вместо строки или дата без времени. Сравнение разных типов в языке запросов не вызывает исключения — оно просто ложно. Проверьте значение и тип через отладчик или выведите параметр в поле выборки.

Можно ли в ГДЕ использовать поле, которого нет в списке ВЫБРАТЬ?

Да, список выбираемых полей и поля условия независимы. Можно отбирать по любому полю таблицы или соединённых таблиц, не включая его в результат. Это нормальная практика — например, отбор по пометке удаления без вывода этого признака.

Как сделать необязательное условие, которое включается только при заполненном параметре?

Стандартный приём — добавить ветку с проверкой самого параметра: ГДЕ (&Склад = НЕОПРЕДЕЛЕНО ИЛИ Товары.Склад = &Склад). В коде передавайте Неопределено, когда фильтр не задан. Альтернатива — программно дописывать текст запроса через СхемуЗапроса, что чище при большом числе опциональных отборов.

Работает ли ПОДОБНО с учётом регистра букв?

Регистрозависимость определяется настройками СУБД, на которой работает база. В большинстве типовых развёртываний MS SQL и PostgreSQL с русской collation сравнение регистронезависимо. Полагаться на это не стоит: если нужен гарантированный результат, приводите обе стороны к одному виду или тестируйте на своём сервере.

Итог

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

Условие ГДЕ строится на параметрах, логических операторах и проверках В, МЕЖДУ, ПОДОБНО, ЕСТЬ NULL. Смешанные условия заключайте в скобки, NULL проверяйте только через ЕСТЬ NULL, а отборы по измерениям регистров выносите в параметры виртуальных таблиц. Перед использованием в рабочем коде проверяйте запрос на копии базы по количеству строк и времени выполнения.