При работе с регистрами, содержащими составные типы данных (например, регистр сведений ВерсииОбъектов или ЖурналПроводки), программисты часто сталкиваются с необходимостью классифицировать объект прямо в запросе. Основная сложность заключается в том, что функция ТИПЗНАЧЕНИЯ() возвращает конкретный тип (например, ДокументСсылка.РеализацияТоваровУслуг), но не говорит напрямую, относится ли этот тип к классу «Документы» или «Справочники».
В этой статье мы разберем несколько эффективных способов решения этой задачи, проанализируем их производительность и выберем наиболее подходящий для Системы компоновки данных (СКД).
Этот способ считается классическим и наиболее производительным, если список типов в базе относительно стабилен. Идея заключается в том, чтобы заранее подготовить массивы всех типов документов и справочников, передать их в параметры запроса и выполнить проверку вхождением в массив.
Рассмотрим по шагам реализацию этого метода:
В (&Параметр).Пример программного кода для подготовки параметров:
// Получаем массив всех типов документов в конфигурации
ТипыДокументов = Документы.ТипВсеСсылки().Типы();
// Получаем массив всех типов справочников
ТипыСправочников = Справочники.ТипВсеСсылки().Типы();
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Т.Объект КАК Объект,
| ВЫБОР
| КОГДА ТИПЗНАЧЕНИЯ(Т.Объект) В (&ТипыДокументов) ТОГДА ""Документ""
| КОГДА ТИПЗНАЧЕНИЯ(Т.Объект) В (&ТипыСправочников) ТОГДА ""Справочник""
| ИНАЧЕ ""Прочее""
| КОНЕЦ КАК КатегорияОбъекта
|ИЗ
| РегистрСведений.ВерсииОбъектов КАК Т";
Запрос.УстановитьПараметр("ТипыДокументов", ТипыДокументов);
Запрос.УстановитьПараметр("ТипыСправочников", ТипыСправочников);
Преимущества: Высокая скорость выполнения на стороне СУБД, так как сравнение типов происходит по внутренним идентификаторам (Numeric ID типа).
Если нам нужно решение, которое будет работать полностью внутри запроса без предварительной подготовки параметров в коде (например, в динамическом списке или сложном отчете СКД), мы можем воспользоваться системным справочником ИдентификаторыОбъектовМетаданных. Этот справочник хранит иерархическую структуру всех объектов конфигурации.
Проанализируем структуру решения:
Пример реализации запроса:
ВЫБРАТЬ
ВерсииОбъектов.Объект КАК Объект,
Идентификаторы.Имя КАК ИмяТипа,
РодителиИдентификаторов.Имя КАК КатегорияМетаданных
ИЗ
РегистрСведений.ВерсииОбъектов КАК ВерсииОбъектов
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ИдентификаторыОбъектовМетаданных КАК Идентификаторы
ПО ТИПЗНАЧЕНИЯ(ВерсииОбъектов.Объект) = Идентификаторы.ТипОплаты // Внимание: используйте поле Тип в актуальных версиях БСП
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ИдентификаторыОбъектовМетаданных КАК РодителиИдентификаторов
ПО Идентификаторы.Родитель = РодителиИдентификаторов.Ссылка
ГДЕ
РодителиИдентификаторов.Имя = "Документы"
Важный нюанс: Поле Тип в справочнике идентификаторов является специфическим (хранит описание типа). В типовых конфигурациях на базе БСП (Библиотеки стандартных подсистем) для связи используется функция ТИПЗНАЧЕНИЯ, которая сопоставляется с данными справочника.
В Системе компоновки данных у нас есть дополнительные инструменты. Если задача стоит просто в отображении текста или условном оформлении, мы можем не усложнять запрос, а использовать Вычисляемые поля или Выражения ресурсов.
Рассмотрим подробнее использование функций общих модулей в выражениях СКД. Мы можем создать функцию в общем модуле (с флагом "Клиент", "Сервер", "Внешнее соединение"):
Функция ЭтоДокумент(Объект) Экспорт
Возврат Документы.ТипВсеСсылки().СодержитТип(ТипЗнч(Объект));
КонецФункции
Затем в настройках СКД на закладке "Вычисляемые поля" добавим поле с выражением: ИмяОбщегоМодуля.ЭтоДокумент(Объект). Однако помните, что вызов функции общего модуля для каждой строки результата может существенно замедлить формирование отчета на больших объемах данных.
Давайте выясним причину, по которой привычные конструкции не работают в запросах. В языке 1С «Документ» — это не конкретный тип данных, а класс объектов. В базе данных под каждый вид документа (например, ЗаказПокупателя) выделяется свой числовой идентификатор типа. Когда вы вызываете ТИПЗНАЧЕНИЯ, SQL-запрос получает конкретное число.
Поскольку общего идентификатора для «всех документов» в таблицах СУБД не существует, платформа требует точного указания типа. Именно поэтому мы используем либо конструкцию ССЫЛКА (если типов немного), либо массив всех возможных типов через параметр.
Часто возникает вопрос: что использовать эффективнее — оператор ССЫЛКА или функцию ТИПЗНАЧЕНИЯ? Проанализируем ситуацию:
ССЫЛКА: Например, Объект ССЫЛКА Документ.РеализацияТоваровУслуг. Это наиболее быстрый способ, так как платформа на уровне трансляции в SQL точно знает, к какой таблице обращаться. Но он неудобен, когда типов десятки или сотни.ТИПЗНАЧЕНИЯ: При сравнении с массивом параметров работает достаточно быстро, но требует передачи списка всех типов из кода.Подведем итог: Если вы работаете в СКД и вам нужно универсальное решение для определения «Справочник или Документ», лучшим вариантом будет Метод 1 (передача массивов типов в параметры). Он обеспечивает максимальную скорость выполнения и корректную работу со всеми объектами метаданных без исключения.