Как передать колонку табличной части в параметр запроса 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке алгоритмов на платформе 1С часто возникает задача отфильтровать данные в запросе по значениям, расположенным в табличной части документа или обработки. Разберем по шагам, как правильно передать колонку табличной части в параметр запроса, какие существуют варианты реализации и на что следует обратить внимание для обеспечения высокой производительности.

Способ 1. Передача колонки в виде массива через оператор "В"

Самый простой и лаконичный способ — выгрузить нужную колонку табличной части в массив с помощью метода ВыгрузитьКолонку() и передать полученный массив в параметр запроса. В самом тексте запроса используется условие с оператором В (&Параметр).

Рассмотрим пример реализации данного подхода:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ЗаказыКлиентов.Номенклатура КАК Номенклатура
    |ИЗ
    |	РегистрНакопления.ЗаказыКлиентов КАК ЗаказыКлиентов
    |ГДЕ
    |	ЗаказыКлиентов.СтатусЗаказа = &СтатусЗаказа
    |	И ЗаказыКлиентов.Номенклатура В (&МассивНоменклатуры)";

Запрос.УстановитьПараметр("СтатусЗаказа", Ложь);
Запрос.УстановитьПараметр("МассивНоменклатуры", Объект.Резерв.ВыгрузитьКолонку("Номенклатура"));

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

Преимущества метода: минимальное количество кода, простота чтения и высокая скорость написания.

Ограничения: если передаваемый массив содержит очень большое количество элементов (более 1000–2000 штук), СУБД (например, MS SQL Server или PostgreSQL) может испытывать сложности с оптимальной компиляцией плана запроса. В SQL-запросе формируется длинный список параметров, что снижает быстродействие.

Способ 2. Помещение табличной части во временную таблицу через пакет запросов

Если требуется обработать большой объем строк или сопоставить несколько колонок табличной части, оптимальным решением является передача всей табличной части в запрос и помещение ее во временную таблицу. В этом случае мы передаем коллекцию целиком в параметр запроса &Резерв и обрабатываем ее в рамках пакета запросов.

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ТЧ.Номенклатура КАК Номенклатура
    |ПОМЕСТИТЬ ВТ_Резерв
    |ИЗ
    |	&Резерв КАК ТЧ
    |ИНДЕКСИРОВАТЬ ПО
    |	Номенклатура
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |	ЗаказыКлиентов.Номенклатура КАК Номенклатура
    |ИЗ
    |	РегистрНакопления.ЗаказыКлиентов КАК ЗаказыКлиентов
    |ГДЕ
    |	ЗаказыКлиентов.СтатусЗаказа = &СтатусЗаказа
    |	И ЗаказыКлиентов.Номенклатура В
    |		(ВЫБРАТЬ
    |			ВТ.Номенклатура
    |		ИЗ
    |			ВТ_Резерв КАК ВТ)";

Запрос.УстановитьПараметр("СтатусЗаказа", Ложь);
Запрос.УстановитьПараметр("Резерв", Объект.Резерв);

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

Важно помнить: при передаче табличной части во временную таблицу условия фильтрации строится через вложенную выборку вида Номенклатура В (ВЫБРАТЬ ВТ.Номенклатура ИЗ ВТ_Резерв КАК ВТ) или через соединение (ПОЕДИНЕНИЕ).

Важные технические нюансы и рекомендации

Для корректной и быстрой работы алгоритмов учитывайте следующие технические особенности платформы 1С:

  1. Контекст работы на управляемых формах (Тонкий клиент). Передать коллекцию формы типа ДанныеФормыКоллекция напрямую в параметр запроса на сервере нельзя. На сервере необходимо предварительно перенести данные в объект базы данных либо преобразовать коллекцию формы в обычную таблицу значений или массив (например, с помощью метода РеквизитФормыВЗначение()).
  2. Использование временных таблиц при работе с программно созданными структурами. При передаче реальной табличной части из объекта типы данных колонок считываются автоматически из метаданных. Однако если вы передаете созданную вручную ТаблицуЗначений, для всех ее колонок обязательно должно быть задано точное ОписаниеТипов. В противном случае платформа выбросит ошибку.
  3. Индексация полей. При создании временных таблиц всегда указывайте инструкцию ИНДЕКСИРОВАТЬ ПО для ключевых полей, по которым в дальнейшем производятся соединения или фильтрация. Это существенно ускоряет выборку на стороне СУБД.
  4. Подготовка данных и удаление дублей. При выгрузке колонки в массив или передаче табличной части рекомендуем избавляться от повторяющихся и незаполненных значений. Дубликаты в массивах негативно сказываются на работе оптимизатора СУБД.
  5. Фильтрация в виртуальных таблицах. Если выборка выполняется из виртуальной таблицы (например, РегистрНакопления.ЗаказыКлиентов.Остатки), передавать фильтрацию по номенклатуре следует непосредственно в параметры самой виртуальной таблицы, а не в блок ГДЕ. Использование блока ГДЕ для виртуальных таблиц заставляет систему сначала рассчитать итоги по всей базе данных и лишь затем отсечь лишние строки.
  6. Работа с несохраненными данными. Учитывайте, что если объект базы данных еще не записан или был изменен в сеансе пользователя, выборка данных непосредственно из табличных частей документов или регистров базы через обычный запрос не вернет несохраненные изменения. В таких случаях данные всегда нужно передавать из текущей коллекции объекта на сервере.

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

← На главную