Как обратиться к реквизиту составного поля регистратора в запросе 1С при большом числе видов документов?

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

При работе с регистрами накопления или сведений в платформе 1С часто возникает задача получить реквизиты документов-регистраторов. Если поле Регистратор имеет составной тип, включающий сотни видов документов (например, более 256), прямое обращение к реквизиту «через точку» вида Регистратор.Реквизит1 вызывает существенную проблему.

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

Выясним причину проблемы и ограничения СУБД

Рассмотрим механизм работы платформа 1С при обращении к реквизитам составного типа. Когда в тексте запроса выполняется обращение Регистратор.Реквизит1, транслятор запросов 1С автоматически генерирует в SQL-запросе левое соединение (LEFT OUTER JOIN) со всеми таблицами документов, входящими в этот составной тип.

Если в составной тип входит более 256 различных документов, запрос сталкивается с жесткими ограничениями некоторых СУБД (например, устаревших версий MS SQL Server) или вызывает падение производительности и аварийное завершение работы компилятора запросов из-за слишком громоздкого плана выполнения.

Важно учитывать, что простое условие ГДЕ ТИПЗНАЧЕНИЯ(Регистратор) = ТИП(...) или ГДЕ Регистратор ССЫЛКА ... без явного приведения типов не предотвратит создание левых соединений со всеми таблицами на этапе построения SQL-запроса.

Вариант 1. Использование явного приведения типов через ВЫРАЗИТЬ

Разберем первый способ решения задачи прямо в запросе. Для того чтобы платформе не пришлось выполнять соединения со всеми возможными таблицами, мы можем принудительно указать конкретные типы документов с помощью функции ВЫРАЗИТЬ.

Посмотрим на пример конструкции условия с ограничением типа:


ГДЕ
    ВЫРАЗИТЬ(РН.Регистратор КАК Документ.РеализацияТоваровУслуг).Реквизит1 = &Значение
    ИЛИ ВЫРАЗИТЬ(РН.Регистратор КАК Документ.ПоступлениеТоваровУслуг).Реквизит1 = &Значение

При таком подходе транслятор запросов построит левые соединения только с теми таблицами документов, которые явно указаны в конструкции ВЫРАЗИТЬ, исключив все остальные виды документов из итогового SQL-запроса.

Вариант 2. Динамическое формирование запроса с объединением таблиц

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

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

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

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


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

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

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

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

Вариант 3. Оптимизация на уровне архитектуры конфигурации

Проанализируем архитектурные решения задачи, которые позволяют упростить запросы и ускорить их выполнение:

  1. Добавление реквизита в сам регистр: Если значение реквизита известно в момент проведения документа, целесообразно добавить соответствующий реквизит прямо в регистр накопления и заполнять его при проведении. В этом случае запрос будет выполняться к одной физической таблице без соединений.
  2. Использование общего реквизита: Если реквизит является сквозным для большинства документов, его можно оформить как ОбщийРеквизит в метаданных. Это облегчит работу с полем в запросах.
  3. Ограничение состава типов регистратора: Если в состав регистраторов включены документы, которые фактически не создают движения по регистру, их следует исключить из состава регистраторов в конфигураторе или воспользоваться объектом ОпределяемыйТип.
← На главную