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