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

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

Запрос 1С: как работает условие «в списке» (оператор В)

Как использовать оператор В и условие «в списке» в запросах 1С: передача массива и списка значений в параметр, отбор по иерархии, типичные ошибки и примеры кода.

Условие «в списке» — один из самых частых приёмов при написании запросов в 1С. Оно позволяет отобрать записи, где значение поля совпадает с любым элементом из заранее подготовленного набора: массива, списка значений или таблицы значений. Реализуется это оператором В в секции ГДЕ и параметром запроса, в который передаётся коллекция.

Типовая ситуация: пользователь отметил несколько контрагентов или номенклатурных позиций в форме, и нужно одним запросом получить по ним данные из регистров и справочников. Вместо цикла с отдельными запросами по каждому элементу — который работает медленно и нагружает сервер СУБД — применяется один запрос с условием ГДЕ Номенклатура В (&СписокНоменклатуры).

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

Синтаксис оператора В и базовый пример

Оператор В проверяет, входит ли значение поля в указанный набор. В языке запросов 1С запись выглядит так:

ВЫБРАТЬ

Продажи.Номенклатура,

СУММА(Продажи.Количество) КАК Количество

ИЗ

РегистрНакопления.Продажи.Обороты КАК Продажи

ГДЕ

Продажи.Номенклатура В (&СписокНоменклатуры)

СГРУППИРОВАТЬ ПО

Продажи.Номенклатура

Параметр &СписокНоменклатуры заполняется перед выполнением запроса методом УстановитьПараметр(). Простейший вариант — массив ссылок:

МассивНоменклатуры = Новый Массив;

МассивНоменклатуры.Добавить(Ссылка1);

МассивНоменклатуры.Добавить(Ссылка2);

Запрос = Новый Запрос(ТекстЗапроса);

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

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

Обратите внимание: в параметр передаётся именно коллекция, а не строка с перечислением значений через запятую. Строка «"Ссылка1, Ссылка2"» будет воспринята как одно значение строкового типа, и условие не сработает так, как ожидает разработчик.

Что можно передать в параметр списка

Платформа принимает в параметр с оператором В несколько типов коллекций, и у каждого есть свои особенности. Выбор зависит от того, откуда берутся данные.

  • Массив — универсальный вариант, когда список формируется программно: перебором выборки, отбором строк табличной части, обработкой данных формы. Наиболее предсказуемый тип.
  • Список значений — удобен, когда список приходит из элемента формы (например, поле списка с множественным выбором) или когда нужны представления элементов. Перед передачей часто выгружают в массив методом ВыгрузитьЗначения(), чтобы исключить дубли и лишние служебные данные.
  • Таблица значений — передаётся целиком как параметр-таблица, но тогда в запросе её нужно сначала поместить во временную таблицу и соединить с основными данными. Это отдельный сценарий, описанный ниже.

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

Сравнение вариантов

Массив

Подходит почти всегда; тип контролируется разработчиком, нет дублей при аккуратном заполнении. Ограничение — нужно формировать программно.

Список значений

Удобен при работе с элементами форм и интерактивным выбором. Перед передачей стоит выгрузить значения и удалить дубли.

Таблица значений

Нужна, когда кроме ссылки передаются дополнительные поля (количество, цена). Требует помещения во временную таблицу и соединения — запрос сложнее.

Отбор по иерархии: В ИЕРАРХИИ

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

ГДЕ

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

В этом случае в параметр передают массив или список ссылок на группы (и/или элементы), а запрос вернёт записи по всем элементам, входящим в эти группы на любом уровне вложенности. Это избавляет от необходимости программно обходить дерево справочника и собирать полный перечень ссылок.

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

Список из таблицы значений: временные таблицы

Если источником списка служит таблица значений — например, результат предыдущего запроса или загруженные из файла данные — её передают как параметр и помещают во временную таблицу. После этого список используется через соединение или вложенный запрос:

ВЫБРАТЬ

ТЗ.Номенклатура КАК Номенклатура

ПОМЕСТИТЬ ВТ_Список

ИЗ

&ТаблицаОтбора КАК ТЗ

;

ВЫБРАТЬ

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

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

ИЗ

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

ГДЕ

Остатки.Номенклатура В (ВЫБРАТЬ ВТ_Список.Номенклатура ИЗ ВТ_Список)

В коде параметр устанавливается так: Запрос.УстановитьПараметр("ТаблицаОтбора", ТаблицаЗначений). Для работы временных таблиц запросу назначают менеджер временных таблиц: Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц.

Такой подход предпочтительнее передачи огромного массива, когда строк много (тысячи и десятки тысяч), и обязателен, когда вместе со ссылкой нужно передать дополнительные данные — например, ожидаемое количество по каждой позиции для последующего сравнения с остатками.

Порядок действий
  1. 1
    Сформируйте массив или список значений со ссылками нужного типа, уберите дубли и пустые значения
  2. 2
    Напишите текст запроса с условием ГДЕ Поле В (&ИмяПараметра)
  3. 3
    Установите параметр методом Запрос.УстановитьПараметр() до вызова Выполнить()
  4. 4
    Выполните запрос и проверьте результат на тестовом наборе, где итог известен заранее
  5. 5
    Если список содержит группы иерархического справочника и нужны вложенные элементы — замените условие на В ИЕРАРХИИ

Типичные ошибки и как их диагностировать

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

Вторая группа ошибок связана с дублями и «мусором» в списке. Список значений из формы может содержать повторяющиеся элементы и пустые ссылки. Дубли не ломают запрос, но увеличивают объём передаваемых данных; пустая ссылка в списке обычно безвредна, но в составных типах может приводить к неожиданным совпадениям.

Третья группа — попытка передать в параметр строку с идентификаторами или перечисление через запятую. Оператор В не разбирает строки: он сравнивает значения как есть. Если источник данных — строка, её нужно сначала разобрать в массив и преобразовать элементы к нужному типу ссылок.

Типичные ошибки
01
Передача строки вместо массива — условие сравнивает поле с одной строкой, результат пустой или ошибка типов
02
Забытый вызов УстановитьПараметр() — запрос падает с сообщением о неустановленном параметре
03
Использование В ИЕРАРХИИ для неиерархического объекта — синтаксическая ошибка при выполнении
04
Передача списка значений с дублями и пустыми ссылками — лишняя нагрузка и неочевидные совпадения
05
Условие В по полю составного типа без контроля типа элементов массива — часть значений молча не совпадает

Производительность и ограничения

Условие В с параметром-списком платформа транслирует в запрос СУБД. При умеренном размере списка (десятки и сотни элементов) это работает быстро, особенно если по полю условия есть индекс — а по ссылочным полям в регистрах он обычно присутствует.

Проблемы начинаются при очень больших списках. Передача массива из десятков тысяч элементов увеличивает время подготовки запроса и объём передаваемых на сервер СУБД данных. В таких случаях надёжнее схема с временной таблицей: данные загружаются один раз, а дальше используется соединение, которое оптимизатор СУБД обрабатывает эффективнее.

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

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

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

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

Совпадает с ожидаемым числом записей по тестовому списку

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

Пустой результат при заведомо существующих данных — проверяйте тип и содержимое параметра

Содержимое параметра перед выполнением
Норма

Коллекция нужного типа, без пустых ссылок и дублей

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

Строка, единичное значение или элементы другого типа

Скорость выполнения
Норма

Запрос отрабатывает быстро, по полю условия есть индекс

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

Заметная задержка при большом списке — переходите на временную таблицу

Альтернативы оператору В

Оператор В — не единственный способ отбора по набору значений. В консоли запросов и в простых сценариях допустимо перечисление значений прямо в тексте: ГДЕ Статус В (ЗНАЧЕНИЕ(Перечисление.Статусы.Новый), ЗНАЧЕНИЕ(Перечисление.Статусы.ВРаботе)). Это удобно для фиксированных наборов перечислений, но не подходит для динамических списков.

Для отбора по диапазону вместо списка используется МЕЖДУ, а для строковых шаблонов — ПОДОБНО. Смешивать эти операторы в одном условии через ИЛИ можно, но при росте числа условий запрос становится трудно читаемым — тогда список в параметре снова оказывается лучшим решением.

В динамических списках форм аналогичную задачу решает отбор через СписокЗначений в элементах отбора компоновки данных — там условие «в списке» задаётся без написания текста запроса вручную, но внутри работает тот же механизм.

Перед передачей списка значений из формы в запрос полезно выполнить ВыгрузитьЗначения() и свернуть массив через соответствие или удаление дублей. Это сокращает параметр и исключает ситуации, когда один и тот же элемент встречается в списке несколько раз после многократного выбора пользователем.
ПЗ
Практическое замечание

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

Можно ли передать в параметр оператора В обычную строку со значениями через запятую?

Нет. Оператор В сравнивает значение поля с каждым элементом коллекции, а строка воспринимается как одно значение. Строку нужно сначала разобрать в массив, преобразовать элементы к типу поля (например, получить ссылки по наименованиям или уникальным идентификаторам) и только потом передавать в параметр.

Чем В ИЕРАРХИИ отличается от обычного В?

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

Запрос с условием В возвращает пустой результат, хотя данные есть. Что проверять первым делом?

Сначала убедитесь, что параметр установлен до вызова Выполнить() и содержит коллекцию, а не строку или единичное значение. Затем проверьте тип элементов: ссылки должны относиться к тому же объекту метаданных, что и поле в условии. Полезно временно вывести содержимое параметра в цикле перед выполнением запроса.

Что лучше для большого списка — массив или временная таблица?

При десятках и сотнях элементов разница незаметна, и массив проще в реализации. При тысячах и десятках тысяч элементов предпочтительнее таблица значений, помещаемая во временную таблицу: соединение с ней оптимизируется СУБД эффективнее, чем гигантский список значений в условии.

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

Используйте отрицание: ГДЕ НЕ Поле В (&Список) или ГДЕ Поле НЕ В (&Список). Учтите, что на больших таблицах такое условие может приводить к полному сканированию. Альтернатива — левое соединение с временной таблицей списка и условие на NULL в поле соединения.

Работает ли условие «в списке» в динамических списках и СКД без ручного запроса?

Да. В схеме компоновки данных и в настройках динамического списка вид сравнения «В списке» доступен в отборах: параметру назначается список значений, и платформа формирует соответствующее условие автоматически. Ручной текст запроса при этом писать не требуется.

Итог

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

Условие «в списке» реализуется оператором В с параметром-коллекцией: массивом, списком значений или таблицей через временную таблицу. Для групп иерархического справочника применяется В ИЕРАРХИИ. Контролируйте тип и чистоту элементов списка, а при больших объёмах переходите на временные таблицы.