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