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