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