Как в СКД настроить отбор по типу документа?

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

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

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

Способ 1. Использование стандартного отбора СКД по типу

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

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

  1. Откроем схему компоновки данных и перейдем на вкладку Настройки.
  2. В табличной части Отбор добавим новое условие.
  3. В качестве левого значения выберем поле Документ (или аналогичное составное ссылочное поле).
  4. В колонке Вид сравнения укажем Тип (если требуется выбрать один вид документа) или В списке типов (если необходимо отбирать несколько типов документов одновременно).
  5. В правом значении выберем нужный тип метаданных из дерева объектов конфигурации.
  6. Вынесем этот отбор в пользовательские настройки (свойство «Включать в пользовательские настройки»), чтобы пользователь мог управлять им прямо на форме отчета.

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

Способ 2. Управление фильтрацией через расширение языка запросов СКД

В исходном запросе часто пытаются реализовать необязательный отбор через громоздкую конструкцию ВЫБОР КОГДА &Параметр = ... ТОГДА ИСТИНА ИНАЧЕ .... Этот подход крайне не рекомендуется: конструкция заставляет СУБД сканировать таблицы целиком, игнорируя доступные индексы.

Вместо этого применим механизм необязательных условий компоновщика — фигурные скобки {ГДЕ ...}. Если параметр не задан пользователем, компоновщик макета СКД просто вырежет условие из финального текста запроса.

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


ВЫБРАТЬ
    ВТ_Документы.Документ КАК Документ,
    ВТ_Документы.Контрагент КАК Контрагент,
    ВТ_Документы.ПолученыКопииДокументов КАК ПолученыКопииДокументов,
    ВТ_Документы.ПолученыОригиналыДокументов КАК ПолученыОригиналыДокументов
ИЗ
    ВТ_Документы КАК ВТ_Документы
{ГДЕ
    ВТ_Документы.Контрагент.* КАК Контрагент,
    ТИПЗНАЧЕНИЯ(ВТ_Документы.Документ) = &ТипДокумента}

Для проверки типа в запросе 1С применяются конструкции:

  1. ТИПЗНАЧЕНИЯ(Поле) = &ТипДокумента или ТИПЗНАЧЕНИЯ(Поле) = ТИП(Документ.РасходнаяНакладная) — получение и сопоставление типа ссылки.
  2. Оператор ССЫЛКА: условие вида ВТ_Документы.Документ ССЫЛКА Документ.РасходнаяНакладная. На уровне СУБД оператор ССЫЛКА работает быстрее всего, так как проверяет код типа таблицы документа.

Способ 3. Оптимизация архитектуры запроса

Проанализируем структуру исходного запроса с точки зрения быстродействия. Конструкция ПОМЕСТИТЬ ВТ_Документы объединяет множество больших таблиц во временную таблицу. В этом случае СУБД вынуждена сначала полностью прочитать все таблицы документов, записать их в TempDB и только потом применить фильтры из завершающего запроса.

Если отказаться от помещения данных во временную таблицу и оставить прямое объединение в основном пакете, компоновщик данных СКД сможет автоматически «пробросить» пользовательский отбор по типу (или по контрагенту) внутрь каждого запроса объединения. В результате СУБД прочитает только ту таблицу, тип которой выбрал пользователь.

Рассмотрим пример оптимизированного запроса без промежуточной временной таблицы:


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

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

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

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

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

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

← На главную