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