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