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

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

Запрос 1С: как проверить значение на вхождение в массив

Как использовать условие ГДЕ поле В (&Массив) в запросе 1С: передача массива параметром, сравнение со списком значений, типичные ошибки и альтернативы.

В языке запросов 1С проверка значения на вхождение в список выполняется оператором В (аналог SQL-конструкции IN). Чаще всего условие записывается как ГДЕ Поле В (&Массив), где параметром передаётся массив, список значений или таблица значений. Это стандартный способ отфильтровать записи по набору ссылок, номенклатурных позиций, контрагентов или любых других значений без построения громоздкой цепочки условий ИЛИ.

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

Как устроен оператор В в языке запросов 1С

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

Базовый пример с явным перечислением выглядит так:

ВЫБРАТЬ

Номенклатура.Ссылка КАК Ссылка

ИЗ

Справочник.Номенклатура КАК Номенклатура

ГДЕ

Номенклатура.Код В ("000001", "000002", "000003")

Явное перечисление удобно только для фиксированных коротких списков. Как только набор значений формируется пользователем или вычисляется в коде, правильнее перейти на параметр. Отрицание условия записывается как НЕ (Поле В (&Массив)) — скобки обязательны, иначе конструктор запроса может интерпретировать выражение не так, как ожидается.

Передача массива в параметр запроса

Чтобы использовать массив в условии ГДЕ, его передают методом УстановитьПараметр объекта запроса. Платформа сама преобразует коллекцию в набор значений для сравнения. Типичный фрагмент кода:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Товары.Ссылка КАК Ссылка,

| Товары.Наименование КАК Наименование

|ИЗ

| Справочник.Номенклатура КАК Товары

|ГДЕ

| Товары.Ссылка В (&СписокНоменклатуры)";

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

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

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

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

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

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

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

Если массив формируется выгрузкой колонки из таблицы значений, используйте Таблица.ВыгрузитьКолонку("ИмяКолонки") — это быстрее ручного обхода циклом и исключает ошибки при добавлении элементов.

Пустой массив и его обработка

Наиболее частая ловушка: если передать пустой массив, условие Поле В (&Массив) не выполнится ни для одной строки, и запрос вернёт пустой результат. Формально это корректное поведение, но в логике прикладного кода пустой отбор часто означает «отбор не задан, показать всё». Эти две трактовки нужно различать явно.

Стандартное решение — проверять заполненность массива до выполнения запроса и либо не добавлять условие в текст, либо использовать приём с признаком «отбор отключён»:

ГДЕ

(&БезОтбора ИЛИ Товары.Ссылка В (&СписокНоменклатуры))

Параметр &БезОтбора устанавливается в Истина, когда массив пуст, и в Ложь, когда отбор нужен. Учтите, что такая конструкция мешает оптимизатору использовать индекс по полю отбора, поэтому на больших таблицах предпочтительнее динамически формировать текст запроса через СтрЗаменить или схему компоновки данных.

Сравнение с вложенным запросом и соединением

Оператор В принимает и вложенный запрос: ГДЕ Поле В (ВЫБРАТЬ ...). Это удобно, когда набор значений нужно получить из базы, а не из кода. Однако при больших объёмах данных вложенный запрос в условии часто работает медленнее, чем соединение с временной таблицей.

Альтернативный подход — поместить массив во временную таблицу через ВЫБРАТЬ ... ПОМЕСТИТЬ с передачей таблицы значений параметром, а затем соединить её с основной таблицей. Такой вариант даёт оптимизатору больше свободы и обычно выигрывает на массивах из тысяч элементов.

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

ГДЕ Поле В (&Массив)

Подходит для небольших и средних списков (десятки и сотни элементов), простой и читаемый синтаксис. Ограничение: на очень больших массивах возможна деградация производительности.

Вложенный запрос в В

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

Временная таблица + соединение

Оптимально для больших массивов и многократного использования списка в пакетном запросе. Требует больше кода: создание менеджера временных таблиц и параметра-таблицы.

Оператор В ИЕРАРХИИ и особые случаи

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

Отдельный сценарий — проверка по нескольким полям одновременно. Язык запросов 1С не поддерживает кортежное сравнение вида (Поле1, Поле2) В (...) напрямую. Обходной путь — соединение с временной таблицей пар значений или разворот условия через И/ИЛИ для каждой пары, что приемлемо только при малом числе комбинаций.

Типичные ошибки и как их найти

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

Вторая типичная проблема — дубли в массиве. Они не ломают запрос, но при большом числе повторов увеличивают накладные расходы. Удалить дубли можно через соответствие или свёртку таблицы значений перед выгрузкой колонки. Третья ошибка — использование условия В с полем, содержащим NULL после левого соединения: NULL никогда не равен элементу списка, поэтому такие строки отбрасываются. При необходимости их учитывать добавляйте условие ИЛИ Поле ЕСТЬ NULL.

Типичные ошибки
01
Передача пустого массива без проверки — запрос молча возвращает ноль строк, что в расчётных механизмах выглядит как потеря данных.
02
Смешение типов в массиве (ссылки и строки) — часть элементов никогда не совпадает с полем, записи пропадают из результата.
03
Использование В с полем, содержащим NULL после левого соединения — такие строки отбрасываются, хотя логически должны попасть в отбор.
04
Отказ от временной таблицы при массиве в десятки тысяч элементов — заметное замедление запроса на больших базах.

Проверка результата и производительность

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

По производительности ориентируйтесь на объём массива. Для списков до нескольких сотен элементов разница между В (&Массив) и временной таблицей практически незаметна. При тысячах и десятках тысяч элементов, а также когда список используется в нескольких запросах пакета, временная таблица с индексом по полю соединения даёт более предсказуемое время выполнения.

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

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

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

Совпадает с ручным отбором по нескольким элементам списка

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

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

Типы элементов массива
Норма

Все элементы имеют тот же тип, что и поле в условии

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

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

Время выполнения
Норма

Запрос отрабатывает за приемлемое для операции время

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

Резкий рост времени при увеличении массива — переходите на временную таблицу

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

Можно ли передать в параметр список значений вместо массива?

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

Как отобрать записи, которых нет в массиве?

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

Почему запрос с условием В возвращает пустой результат?

Три основные причины: передан пустой массив, типы элементов не совпадают с типом поля (например, строки вместо ссылок) или поле содержит NULL. Проверяйте содержимое параметра и типы элементов перед выполнением запроса.

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

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

Когда вместо массива лучше использовать временную таблицу?

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

Можно ли проверить вхождение сразу по двум полям?

Кортежное сравнение вида (Поле1, Поле2) В (...) язык запросов 1С не поддерживает. Решение — соединение с временной таблицей пар значений по обоим полям или, при малом числе комбинаций, развёрнутое условие через И и ИЛИ.

Итог

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

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