Как соединить таблицы в запросе, используя данные с формы?

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

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

Этот метод является стандартным и наиболее производительным для подобных операций. Разберем его по шагам.

Шаг 1. Подготовка и типизация таблицы значений на стороне клиента/сервера

Прежде чем передавать данные в запрос, их нужно подготовить. Источником может быть табличная часть документа, таблица значений на форме или любая другая коллекция. Ключевой момент — таблица, передаваемая в запрос, должна быть типизированной. Это означает, что для каждой ее колонки должен быть явно задан тип данных. Если этого не сделать, система 1С может неверно интерпретировать структуру данных внутри запроса, что приведет к ошибкам.

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


// Создаем новую ТаблицуЗначений
ТаблицаПриемник = Новый ТаблицаЗначений;

// Добавляем колонку и обязательно указываем ее тип.
// В данном случае, это строка длиной 150 символов.
ТаблицаПриемник.Колонки.Добавить("Сотрудник", Новый ОписаниеТипов("Строка",,,, Новый КвалификаторыСтроки(150))); 

// Далее необходимо заполнить эту таблицу данными с формы
// Например, в цикле из другой таблицы или табличной части
Для Каждого ЭлементСписка Из СписокСотрудниковНаФорме Цикл
    НоваяСтрока = ТаблицаПриемник.Добавить();
    НоваяСтрока.Сотрудник = ЭлементСписка.Наименование;
КонецЦикла;

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

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

Теперь, когда у нас есть подготовленная таблица, ее нужно передать в запрос. Для этого используется метод УстановитьПараметр() объекта Запрос. Внутри самого запроса мы обращаемся к этому параметру через символ амперсанда (&).

Чтобы с переданными данными можно было полноценно работать (соединять, индексировать), их необходимо поместить во временную таблицу с помощью конструкции ПОМЕСТИТЬ. Это стандартная и рекомендуемая практика.

  1. Создаем объект Запрос.
  2. Устанавливаем нашу таблицу в качестве параметра.
  3. В тексте запроса первым пакетом выбираем данные из параметра и помещаем их во временную таблицу.

Посмотрим на пример первого пакета запроса:


Запрос = Новый Запрос;
Запрос.УстановитьПараметр("ТаблицаИсточник", ТаблицаПриемник);

Запрос.Текст = 
"ВЫБРАТЬ
|    ТаблицаИсточник.Сотрудник КАК СотрудникТекст
|ПОМЕСТИТЬ втТаблицаИсточник
|ИЗ
|    &ТаблицаИсточник КАК ТаблицаИсточник";

Проанализируем этот код:

Использование временных таблиц критически важно для производительности, особенно при работе с большими объемами данных, так как СУБД может создавать для них индексы, что значительно ускоряет последующие соединения.

Шаг 3. Соединение временной таблицы с таблицами базы данных

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

Дополним наш запрос вторым пакетом, где мы соединим временную таблицу втТаблицаИсточник со справочником Сотрудники и другими регистрами для получения дополнительной информации.

Посмотрим на полный текст запроса с соединением:


Запрос = Новый Запрос;
Запрос.УстановитьПараметр("ТаблицаИсточник" , ТаблицаПриемник ); 

Запрос.Текст = 
"ВЫБРАТЬ
|    ТаблицаИсточник.Сотрудник КАК СотрудникТекст
|ПОМЕСТИТЬ втТаблицаИсточник
|ИЗ
|    &ТаблицаИсточник КАК ТаблицаИсточник
|;
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
|    втТаблицаИсточник.СотрудникТекст,
|    Сотрудники.Ссылка КАК Сотрудник,
|    Сотрудники.Код,
|    Сотрудники.ФизическоеЛицо.ДатаРождения КАК ФизическоеЛицоДатаРождения
|ИЗ
|    втТаблицаИсточник КАК втТаблицаИсточник
|        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Сотрудники КАК Сотрудники
|        ПО втТаблицаИсточник.СотрудникТекст = Сотрудники.Наименование";

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

Здесь ключевая строка — условие соединения: ПО втТаблицаИсточник.СотрудникТекст = Сотрудники.Наименование. Мы связываем нашу временную таблицу (с данными из формы) со справочником сотрудников по наименованию.

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

Соединение трех и более таблиц

В 1С нет практических ограничений на количество соединяемых таблиц. Принцип соединения нескольких таблиц — последовательная "цепочка". Вы соединяете таблицу А с таблицей Б, затем результат этого соединения (или одну из исходных таблиц) — с таблицей В, и так далее.

Например, если у вас есть таблица с формы (втТаблицаИсточник), таблица соответствий (втСоответствие) и таблица из базы данных (Справочник.Номенклатура), схема соединения будет выглядеть так:

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

При построении цепочки соединений очень важно правильно выбирать тип соединения (ЛЕВОЕ, ВНУТРЕННЕЕ). Неверно выбранный тип, например, ВНУТРЕННЕЕ СОЕДИНЕНИЕ вместо ЛЕВОЕ, может "обрезать" строки из итогового результата, если для какой-то записи из левой таблицы не найдется соответствия в правой.

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

← На главную