Разработка и Конфигурация · 11 мин
Конструкция ГДЕ В в запросе 1С: применение и примеры
Как работает конструкция ГДЕ В в запросе 1С: синтаксис, передача таблицы значений и массива в параметр, типичные ошибки и способы проверки результата.
Конструкция ГДЕ В (в английском синтаксисе — WHERE IN) в языке запросов 1С проверяет, входит ли значение поля в заданный набор. Набором может быть перечисление значений в скобках, вложенный запрос или параметр, содержащий массив, список значений либо таблицу значений. Это один из самых востребованных инструментов фильтрации: через него отбирают документы по списку контрагентов, товары по группе номенклатуры, проводки по набору счетов.
Главная сложность для начинающих разработчиков — не сам синтаксис, а понимание того, что именно можно передать в параметр и как платформа обрабатывает такой отбор. Неправильно подготовленный параметр приводит к ошибке исполнения запроса или к пустой выборке, хотя данные в базе есть. Ниже разобраны все варианты применения ГДЕ В, ограничения и способы проверить корректность результата.
Базовый синтаксис конструкции ГДЕ В
Простейшая форма — перечисление значений прямо в тексте запроса через запятую в круглых скобках:
ГДЕ
Номенклатура.ВидНоменклатуры В (
ЗНАЧЕНИЕ(Перечисление.ВидыНоменклатуры.Товар),
ЗНАЧЕНИЕ(Перечисление.ВидыНоменклатуры.Услуга)
)
Такой вариант уместен, когда набор значений известен заранее и неизменен: значения перечислений, предопределённые элементы, конкретные константы строк или чисел. Значения в списке должны быть сравнимы с типом поля — нельзя смешивать ссылку на справочник и строку без приведения типов.
Обратная проверка выполняется через НЕ В — отбор всех записей, где значение поля не входит в набор. Учтите, что НЕ В не возвращает строки, где поле равно NULL: для них условие вычисляется как неопределённое, и такие записи выпадают из выборки. Если это критично, добавляйте обработку NULL через ЕСТЬNULL или объединение условий через ИЛИ.
Отбор по массиву или списку значений через параметр
На практике набор значений чаще формируется в коде, а не зашит в текст запроса. В этом случае в запросе пишется В (&ИмяПараметра), а в параметр передаётся массив, список значений или таблица значений:
МассивКонтрагентов = Новый Массив;
МассивКонтрагентов.Добавить(Контрагент1);
МассивКонтрагентов.Добавить(Контрагент2);
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РеализацияТоваровУслуг.Ссылка
|ИЗ
| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
|ГДЕ
| РеализацияТоваровУслуг.Контрагент В (&Контрагенты)";
Запрос.УстановитьПараметр("Контрагенты", МассивКонтрагентов);
Результат = Запрос.Выполнить();
Платформа сама разворачивает массив в список значений при исполнении запроса. Тип элементов массива должен совпадать с типом проверяемого поля: для ссылочного поля — ссылки, для строкового — строки. Смешанный массив из ссылок разных типов допустим, если поле составного типа и включает эти типы.
Если массив пуст, условие В (&Параметр) не вернёт ни одной строки. Это частая причина «запрос ничего не нашёл, хотя данные есть». Перед выполнением проверяйте заполненность коллекции в коде и либо не выполняйте запрос вовсе, либо меняйте его текст, убирая условие.
- 1Сформируйте массив или список значений с элементами нужного типа
- 2В тексте запроса напишите условие: Поле В (&ИмяПараметра)
- 3Вызовите Запрос.УстановитьПараметр с именем параметра и коллекцией
- 4Выполните запрос и проверьте, что выборка не пуста при заведомо подходящих данных
- 5Добавьте проверку на пустую коллекцию перед выполнением запроса
Отбор по таблице значений и временной таблице
Когда отбирать нужно не по одному полю, а по комбинации — например, по паре «номенклатура + характеристика», — в параметр передают таблицу значений. В запросе её помещают во временную таблицу и соединяют с основными данными:
Запрос.Текст =
"ВЫБРАТЬ
| Таб.Номенклатура КАК Номенклатура,
| Таб.Характеристика КАК Характеристика
|ПОМЕСТИТЬ ВТ_Отбор
|ИЗ
| &ТаблицаОтбора КАК Таб
|;
|ВЫБРАТЬ
| Остатки.Номенклатура,
| Остатки.КоличествоОстаток
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Отбор КАК Отбор
| ПО Остатки.Номенклатура = Отбор.Номенклатура
| И Остатки.Характеристика = Отбор.Характеристика";
Этот подход корректнее и быстрее, чем перечисление пар через В с несколькими условиями ИЛИ. Кроме того, временную таблицу можно проиндексировать (ИНДЕКСИРОВАТЬ ПО), что заметно ускоряет соединение на больших объёмах данных.
Конструкция В с таблицей значений напрямую (без помещения во временную таблицу) в современных версиях платформы не используется: параметр-таблица всегда сначала материализуется через ПОМЕСТИТЬ. Если вы встречаете в старом коде попытку написать В (&ТаблицаЗначений), переписывайте через временную таблицу и соединение.
Вложенный запрос как набор значений
Третий вариант — вложенный запрос в скобках после В. Набор значений тогда вычисляется самим запросом из данных базы:
ГДЕ
Продажи.Номенклатура В (
ВЫБРАТЬ
Номенклатура.Ссылка
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
Номенклатура.Родитель = &Группа
)
Вложенный запрос должен возвращать ровно одно поле, тип которого сравним с проверяемым выражением. Если выбрать два поля, запрос не выполнится — платформа выдаст ошибку ещё на этапе проверки текста в консоли запросов или при исполнении.
Для отбора по иерархии удобна связанная конструкция В ИЕРАРХИИ: она проверяет вхождение элемента в группу справочника с учётом всех уровней вложенности. Например, Номенклатура В ИЕРАРХИИ (&Группа) отберёт элементы как самой группы, так и всех её подгрупп, без рекурсивных вложенных запросов.
Производительность и ограничения
Каждый вариант ГДЕ В по-разному влияет на скорость выполнения. Список констант в скобках — самый дешёвый: оптимизатор СУБД превращает его в простое сравнение. Параметр-массив тоже обычно работает быстро, но при очень больших массивах (десятки тысяч элементов) время подготовки запроса растёт, и лучше перейти на временную таблицу.
Вложенный запрос в В может выполняться медленнее эквивалентного соединения таблиц, особенно если вложенный запрос возвращает много строк. В большинстве случаев связку «вложенный запрос в В» можно переписать через ВНУТРЕННЕЕ СОЕДИНЕНИЕ с тем же результатом и более предсказуемым планом выполнения.
Ограничения, о которых стоит помнить: значения в наборе должны быть сравнимы с полем по типу; В не работает с полями неограниченной длины и хранилищами значений; при отборе виртуальных таблиц регистров условие лучше передавать в параметры виртуальной таблицы, а не в общее ГДЕ, — это уменьшает объём вычисляемых данных.
Сравнение вариантов набора значений
Подходит для фиксированных наборов: перечисления, предопределённые элементы. Не работает, если значения известны только во время выполнения.
Универсальный вариант для списков, сформированных в коде. Требует проверки на пустой массив и совпадения типов элементов.
Когда набор вычисляется из данных базы. На больших объёмах часто выгоднее заменить соединением таблиц.
Для отбора по нескольким полям одновременно и для очень больших списков. Требует больше кода, но даёт лучший контроль и индексацию.
Типичные ошибки и их диагностика
Самая распространённая ошибка — передача в параметр одиночного значения вместо коллекции. Если записать УстановитьПараметр("Контрагенты", Контрагент), где переменная содержит одну ссылку, запрос может выполниться без ошибки, но поведение зависит от контекста, и надёжнее всегда передавать массив даже из одного элемента. Для одиночного значения используйте обычное равенство = &Параметр.
Вторая частая проблема — несовпадение типов: поле составного типа, а в массиве ссылки только одного вида, или наоборот — поле конкретного типа, а в списке попались значения другого типа. В первом случае отбор формально сработает, во втором — запрос завершится ошибкой несоответствия типов.
Третья группа ошибок связана с логикой: условие НЕ В без учёта NULL, пустой массив, забытый отбор помеченных на удаление элементов во вложенном запросе. Каждая из них не вызывает ошибки исполнения, поэтому обнаруживается только при проверке результата на контрольных данных.
Как проверить корректность запроса
Перед переносом запроса в код проверяйте его в консоли запросов: задайте параметры теми же типами, что будут в коде, и сравните количество строк с ожидаемым. Если используется массив — сформируйте в консоли список значений с теми же элементами.
Контрольная проверка результата: возьмите одну заведомо подходящую запись и убедитесь, что она есть в выборке; затем одну заведомо неподходящую — и убедитесь, что её нет. Это простое действие отлавливает большинство логических ошибок с В и НЕ В до того, как запрос попадёт в рабочий код.
Как проверить результат
Совпадает с ручным подсчётом по отбору в списке
Меньше ожидаемого — возможны NULL, пустой параметр или лишние условия
Присутствует в выборке
Отсутствует — проверяйте типы значений в параметре
Отсутствует в выборке
Присутствует — условие сформулировано неверно или применено не к тому полю
Если список значений для отбора формируется пользователем в форме, удобно хранить его в списке значений и передавать в запрос напрямую — платформа примет его так же, как массив. Это избавляет от лишнего преобразования коллекций.
Частые вопросы о конструкции ГДЕ В
Можно ли передать в параметр конструкции В список значений, а не массив?
Да, платформа принимает массив, список значений и таблицу значений. Список значений удобен, когда набор формируется в форме. Главное — чтобы типы элементов совпадали с типом проверяемого поля.
Почему запрос с ГДЕ В возвращает пустую выборку, хотя данные есть?
Чаще всего причина в пустом массиве в параметре: условие вхождения в пустой набор ложно для всех строк. Также проверьте совпадение типов элементов и поля, а для НЕ В — наличие NULL в проверяемом поле.
Чем В ИЕРАРХИИ отличается от обычного В?
В ИЕРАРХИИ проверяет принадлежность элемента группе иерархического справочника с учётом всех вложенных подгрупп. Обычное В сравнивает значение только с явно перечисленными элементами без учёта иерархии.
Что быстрее: вложенный запрос в В или соединение таблиц?
На небольших объёмах разница незаметна. На больших данных внутреннее соединение обычно даёт более предсказуемый план выполнения, особенно если временная таблица проиндексирована. При сомнениях сравните оба варианта на реальных данных.
Можно ли использовать ГДЕ В с полями составного типа?
Можно, если все значения набора входят в состав типа поля. Если в списке окажется значение типа, не входящего в составной тип поля, запрос завершится ошибкой несоответствия типов.
Как отобрать по нескольким полям одновременно, например по номенклатуре и складу?
Передайте таблицу значений с нужными колонками в параметр, поместите её во временную таблицу и выполните внутреннее соединение по всем полям. Перечислять пары через В и ИЛИ неэффективно и тяжело читается.
Что важно запомнить
ГДЕ В проверяет вхождение значения в набор: константы в скобках, параметр с массивом или списком, вложенный запрос с одним полем. Для отбора по нескольким полям используйте временную таблицу и соединение. Всегда проверяйте коллекцию на пустоту и совпадение типов, а результат — на контрольных записях.