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