Как получить данные из табличной части документа-регистратора в запросе к регистру накопления?

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

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

Почему это сложная задача?

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

Способ №1: Использование временных таблиц и объединения

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

Разберем алгоритм по шагам:

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

Пример реализации запроса с использованием ОБЪЕДИНИТЬ ВСЕ:


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

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

ВЫБРАТЬ
    ПоступлениеТоваровУслугТовары.Номенклатура,
    ПоступлениеТоваровУслугТовары.Количество,
    ПоступлениеТоваровУслугТовары.Ссылка
ИЗ
    Документ.ПоступлениеТоваровУслуг.Товары КАК ПоступлениеТоваровУслугТовары;

ВЫБРАТЬ
    Регистр.Регистратор,
    вт_табличныечасти.Номенклатура,
    вт_табличныечасти.Количество
ИЗ
    РегистрНакопления.Взаиморасчеты.Обороты КАК Регистр
ВНУТРЕННЕЕ СОЕДИНЕНИЕ вт_табличныечасти КАК вт_табличныечасти
    ПО Регистр.Регистратор = вт_табличныечасти.Ссылка;

Способ №2: Фильтрация через виртуальную таблицу

Если вам нужно выбрать данные только по конкретному виду документа, используйте фильтр по ССЫЛКА в условии ГДЕ. Это позволит оптимизатору запросов работать эффективнее.


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

ВЫБРАТЬ 
    РасходнаяНакладнаяЗапасы.Номенклатура КАК Номенклатура, 
    ВременнаяТаблица.Регистратор КАК Регистратор 
ИЗ 
    ВременнаяТаблица КАК ВременнаяТаблица 
ЛЕВОЕ СОЕДИНЕНИЕ Документ.РасходнаяНакладная.Запасы КАК РасходнаяНакладнаяЗапасы 
    ПО ВременнаяТаблица.Регистратор = РасходнаяНакладнаяЗапасы.Ссылка;

Архитектурные рекомендации: когда запросы не помогают

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

  1. Регистр сведений «дублер»: создайте регистр сведений, который будет заполняться при проведении документа. Туда записываются нужные данные табличной части в «плоском» виде. Чтение из одной таблицы всегда быстрее, чем сборка данных из множества документов.
  2. Индексация: если вы используете временные таблицы, обязательно индексируйте поле Регистратор (ссылка), по которому происходит соединение.
  3. Избегайте «ВЫРАЗИТЬ»: использование этого оператора в условии соединения ПО часто блокирует использование индексов, что делает запрос крайне медленным.

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

← На главную