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