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

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

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

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

Причина проблемы: как СКД обрабатывает пакетные запросы

Рассмотрим ситуацию, описанную в вопросе. Разработчик помещает данные из регистра РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты во временную таблицу ПолныеДанные, а затем пытается последовательно выбрать из нее записи, фильтруя их по типам документов (Перемещение, Продажа, Переоценка). В консоли запросов такой пакет вернет несколько таблиц, но СКД — это не просто инструмент выполнения запросов, это построитель иерархических структур. Для СКД один «Набор данных — запрос» должен возвращать одну плоскую таблицу-результат. Именно поэтому поля из первых запросов пакета игнорируются.

Метод 1. Использование нескольких наборов данных (Data Sets)

Это самый «чистый» и правильный с точки зрения архитектуры СКД подход. Вместо того чтобы писать один громоздкий пакетный запрос, мы разделим его на несколько независимых наборов данных.

Разберем по шагам, как это реализовать:

  1. Перейдем на закладку Наборы данных в схеме компоновки.
  2. Вместо одного набора создадим четыре: НаборПеремещения, НаборПродажи, НаборПереоценка и НаборПрочие.
  3. В каждом наборе пропишем запрос напрямую к регистру или к нужным таблицам с соответствующим фильтром ГДЕ Регистратор ССЫЛКА Документ....
  4. В настройках отчета (вкладка Настройки) добавим несколько группировок или таблиц. Для каждой части отчета можно указать, из какого набора данных брать поля.

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

Метод 2. Объединение данных в одну «широкую» таблицу (UNION ALL)

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

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


ВЫБРАТЬ
    ПолныеДанные.Номенклатура,
    ПолныеДанные.Количество КАК ПеремещениеКоличество,
    0 КАК ПродажиКоличество,
    "Перемещение" КАК ТипОперации
ИЗ
    ПолныеДанные КАК ПолныеДанные
ГДЕ
    ПолныеДанные.Регистратор ССЫЛКА Документ.ПеремещениеТоваров

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

ВЫБРАТЬ
    ПолныеДанные.Номенклатура,
    0,
    ПолныеДанные.Количество,
    "Продажа"
ИЗ
    ПолныеДанные КАК ПолныеДанные
ГДЕ
    ПолныеДанные.Регистратор ССЫЛКА Документ.ОтчетОРозничныхПродажах

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

Метод 3. Связи наборов данных (Left Join средствами СКД)

Если данные из разных запросов должны находиться в одной строке (например, мы хотим видеть остатки и обороты по разным типам документов в одной строке по конкретной номенклатуре), используем механизмы связи.

Выполним следующие действия:

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

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

Метод 4. Разделение через поле-селектор и группировки

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

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


ВЫБРАТЬ
    ПолныеДанные.Регистратор,
    ПолныеДанные.Номенклатура,
    ВЫБОР
        КОГДА ПолныеДанные.Регистратор ССЫЛКА Документ.ПеремещениеТоваров ТОГДА "1. Перемещения"
        КОГДА ПолныеДанные.Регистратор ССЫЛКА Документ.ОтчетОРозничныхПродажах ТОГДА "2. Продажи"
        ИНАЧЕ "3. Прочее"
    КОНЕЦ КАК КатегорияДокумента,
    ПолныеДанные.Количество
ИЗ
    ПолныеДанные КАК ПолныеДанные

Теперь в настройках СКД мы можем сделать верхнеуровневую группировку по полю КатегорияДокумента. В результате отчет будет разбит на визуальные блоки. Для каждой такой группировки можно задать собственный макет оформления или заголовок.

Метод 5. Передача данных через «Набор данных — объект»

Если логика получения данных слишком сложна для языка запросов (например, требуется сложный пересчет остатков с учетом множества условий), проанализируем вариант использования внешней таблицы значений. Мы можем сформировать пакетный запрос в программном коде модуля отчета, получить все нужные таблицы, объединить их или обработать нужным образом, а затем передать результат в СКД.

Для этого в схеме создается Набор данных - объект, которому назначается имя (например, ТаблицаРезультат). В коде инициализации отчета пишется передача данных:


ВнешниеНаборыДанных = Новый Структура;
ВнешниеНаборыДанных.Вставить("ТаблицаРезультат", ТЗ_С_Данными);

ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, ДанныеРасшифровки);

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

Важные рекомендации по оптимизации

При выборе метода стоит учитывать нагрузку на систему:

Таким образом, для решения задачи вывода данных из разных частей логики запроса в СКД, следует отказаться от попытки прочитать "промежуточные" результаты пакета. Вместо этого нужно либо разделять запросы на разные наборы данных, либо объединять их в одну финальную выборку с разделением по колонкам или категориям.

← На главную