Как получить данные из массива ссылок на документы разных типов в одном запросе

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

При разработке на платформе 1С:Предприятие 8 часто возникает задача: на входе имеется массив ссылок, содержащий документы совершенно разных типов (например, «Прием на работу», «Отпуск», «Увольнение»), и из них нужно выгрузить общие данные, такие как Сотрудник и Период, во временную таблицу для дальнейшей обработки. Поскольку ссылки относятся к разным таблицам базы данных, простое обращение через точку в запросе к параметру-массиву невозможно.

Разберем детально, как решить эту задачу эффективно, учитывая особенности производительности и типизации данных.

Способ 1. Использование конструкции ОБЪЕДИНИТЬ ВСЕ

Самый прямой технический путь — это обращение к каждой физической таблице документа, который может встретиться в массиве. Мы выбираем нужные поля из каждой таблицы и фильтруем результат по нашему массиву. Чтобы объединить эти данные в одну выборку, используется оператор ОБЪЕДИНИТЬ ВСЕ.

Рассмотрим пример построения такого запроса:


ВЫБРАТЬ
    ДокПрием.Ссылка КАК Ссылка,
    ДокПрием.Сотрудник КАК Сотрудник,
    ДокПрием.ПериодРегистрации КАК Период
ПОМЕСТИТЬ ВТ_Данные
ИЗ
    Документ.ПриемНаРаботу КАК ДокПрием
ГДЕ
    ДокПрием.Ссылка В (&МассивСсылок)

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    ДокОтпуск.Ссылка,
    ДокОтпуск.Сотрудник,
    ДокОтпуск.ДатаНачала
ИЗ
    Документ.Отпуск КАК ДокОтпуск
ГДЕ
    ДокОтпуск.Ссылка В (&МассивСсылок)

Важный нюанс: при использовании ОБЪЕДИНИТЬ ВСЕ крайне важно, чтобы количество полей, их порядок и типы данных в каждой части запроса совпадали. Если в одном документе поле называется Дата, а в другом ПериодРегистрации, мы должны привести их к общему псевдониму, чтобы во временной таблице ВТ_Данные колонки были типизированы единообразно.

Способ 2. Программное формирование текста запроса

Если типов документов много или их состав заранее неизвестен, писать запрос вручную нецелесообразно. Проанализируем ситуацию: нам гораздо выгоднее составить текст запроса динамически в коде 1С. Это позволит избежать ошибок при изменении состава метаданных и сократит объем рутины.

Рассмотрим алгоритм реализации:

  1. Создаем массив уникальных типов, которые реально присутствуют в исходном массиве ссылок.
  2. Для каждого типа получаем имя таблицы метаданных.
  3. Формируем текстовые блоки ВЫБРАТЬ ... ИЗ ... и соединяем их строкой ОБЪЕДИНИТЬ ВСЕ.

Пример кода для динамической сборки:


ТекстЗапроса = "";
МассивТипов = Новый Массив;

// Собираем только уникальные типы документов из массива ссылок
Для Каждого Ссылка Из МассивСсылок Цикл
    ТипСсылки = ТипЗнч(Ссылка);
    Если МассивТипов.Найти(ТипСсылки) = Неопределено Тогда
        МассивТипов.Добавить(ТипСсылки);
    КонецЕсли;
КонецЦикла;

Для Каждого ТекущийТип Из МассивТипов Цикл
    МетаданныеОбъекта = Метаданные.НайтиПоТипу(ТекущийТип);
    ИмяТаблицы = МетаданныеОбъекта.ПолноеИмя();
    
    Если ТекстЗапроса <> "" Тогда
        ТекстЗапроса = ТекстЗапроса + " ОБЪЕДИНИТЬ ВСЕ ";
    КонецЕсли;
    
    ТекстЗапроса = ТекстЗапроса + 
        "ВЫБРАТЬ Ссылка, Сотрудник, Период ИЗ " + ИмяТаблицы + " ГДЕ Ссылка В (&МассивСсылок)";
КонецЦикла;

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

Способ 3. Оптимизация через предварительную загрузку в ВТ

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

Правильным подходом будет предварительная загрузка массива во временную таблицу. Однако стоит помнить, что в параметрах запроса нельзя просто передать массив для создания ВТ с сохранением типизации ссылок разных типов. Рекомендуем сначала создать ТаблицаЗначений, типизировать колонку и передать её в запрос.

Разберем этот метод по шагам:

  1. Создаем объект ТаблицаЗначений.
  2. Добавляем колонку Ссылка с описанием типов, включающим все возможные типы документов из массива.
  3. Загружаем массив в эту таблицу.
  4. Передаем таблицу в запрос, индексируем её и соединяем с таблицами документов (ВНУТРЕННЕЕ СОЕДИНЕНИЕ).

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

Нюансы типизации и использования характеристик

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

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

Использование объекта СхемаЗапроса

Для более продвинутых сценариев вместо простой конкатенации строк рекомендуем использовать объект СхемаЗапроса. Это мощный инструмент платформы, который позволяет программно манипулировать структурой запроса (добавлять источники, условия, объединения), гарантируя синтаксическую корректность результирующего текста.

Проанализируем преимущества СхемаЗапроса:

Таким образом, выбор конкретного метода зависит от количества типов документов и объема данных в массиве. Для 2-3 типов достаточно простого объединения, для динамических систем лучше использовать сборку текста по метаданным, а для высоконагруженных систем — предварительную загрузку во временную таблицу с индексацией.

← На главную