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