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

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

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

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

Способ 1. Выгрузка колонки в массив параметров

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

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

Посмотрим на пример кода:


// Сворачиваем таблицу для исключения повторяющихся элементов
ТаблицаЗначений.Свернуть("Номенклатура");

// Выгружаем данные колонки в массив
МассивНоменклатуры = ТаблицаЗначений.ВыгрузитьКолонку("Номенклатура");

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

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

Ограничения метода с массивом:

  1. Конструкция В (&Массив) на уровне СУБД разворачивается в оператор IN (...). При объеме массива более 1000–2000 элементов это может приводить к ошибкам ограничений СУБД по максимальному числу параметров и к существенному замедлению построения плана запроса.
  2. Массив не поддерживает индексацию внутри запроса и не позволяет выполнять полноценные соединения таблиц.

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

Проанализируем второй способ, который является стандартом разработки при больших или непредсказуемых объемах данных. Мы передаем таблицу значений целиком или только требуемую колонку в параметр запроса и помещаем ее во временную таблицу с помощью конструкции ПОМЕСТИТЬ.

Если в исходной таблице много лишних колонок, можно скопировать только нужную колонку методом Скопировать():


// Копируем только интересующую колонку
ОдноколоночнаяТЗ = ТаблицаЗначений.Скопировать(, "Номенклатура");
ОдноколоночнаяТЗ.Свернуть("Номенклатура");

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

Запрос.УстановитьПараметр("ТЗ", ОдноколоночнаяТЗ);
РезультатЗапроса = Запрос.Выполнить();

Обратите внимание на важные детали при работе с временными таблицами:

  1. Индексация: Использование директивы ИНДЕКСИРОВАТЬ ПО ускоряет операции соединения таблиц на стороне СУБД.
  2. Уникальность: Использование ВЫБРАТЬ РАЗЛИЧНЫЕ позволяет отсечь дубликаты на этапе помещения во временную таблицу.
  3. Типизация: Если таблица значений создается программно с нуля, необходимо явно определять типы колонок через ОписаниеТипов при вызове метода Колонки.Добавить(), либо приводить их в тексте запроса с помощью функции ВЫРАЗИТЬ().

Способ 3. Передача данных с управляемой формы на сервер

Рассмотрим ситуацию, когда таблица находится на клиенте или отображается в элементах управляемой формы (тип ДанныеФормыКоллекция). Передать такую коллекцию напрямую в запрос нельзя.

В серверном контексте формы необходимо выполнить преобразование коллекции формы в полноценный объект ТаблицаЗначений с помощью платформенной функции ДанныеФормыВЗначение():


&НаСервере
Процедура ОбработатьДанныеФормыНаСервере()

    // Преобразуем данные формы в таблицу значений
    ТЗ = ДанныеФормыВЗначение(Объект.Товары, Тип("ТаблицаЗначений"));
    
    // Выгружаем нужную колонку в массив или передаем таблицу в запрос
    МассивНоменклатуры = ТЗ.ВыгрузитьКолонку("Номенклатура");
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Номенклатура.Ссылка КАК Ссылка,
        |   Номенклатура.Артикул КАК Артикул
        |ИЗ
        |   Справочник.Номенклатура КАК Номенклатура
        |ГДЕ
        |   Номенклатура.Ссылка В (&МассивНоменклатуры)";
        
    Запрос.УстановитьПараметр("МассивНоменклатуры", МассивНоменклатуры);
    Выборка = Запрос.Выполнить().Выбрать();
    
    Пока Выборка.Следующий() Цикл
        // Обработка данных
    КонецЦикла;

КонецПроцедуры

Сравнение подходов

Подведем итог и выделим критерии выбора подходящего способа:

  1. Массив через ВыгрузитьКолонку(): Оптимален для небольших выборок (до нескольких сотен строк) и простых условий фильтрации ГДЕ Поле В (&Параметр).
  2. Временная таблица через &ТЗ: Рекомендуется для средних и больших объемов данных, а также в сценариях, требующих выполнения ВНУТРЕННЕЕ СОЕДИНЕНИЕ или ЛЕВОЕ СОЕДИНЕНИЕ с индексацией полей.
← На главную