Как найти документы по значению Ложь в дополнительных реквизитах типа Булево

Программист 1С v8.3 (Управляемые формы) 1С:Комплексная автоматизация Управленческий учет
← На главную

При работе с подсистемой «Свойства» в типовых конфигурациях 1С (таких как КА 2.4, ERP 2 или УТ 11) программисты часто сталкиваются с неочевидным поведением запросов. Рассмотрим ситуацию: в документ добавлен дополнительный реквизит с типом Булево. Когда в документе установлена «галочка» (значение Истина), запрос успешно находит документ. Однако, как только мы пытаемся найти документы, где галочка снята (значение Ложь), запрос возвращает пустой результат. В этой статье мы подробно разберем, почему это происходит и как правильно составить запрос для решения этой задачи.

Почему стандартный запрос не видит значение Ложь

Для начала проанализируем, как 1С хранит данные дополнительных реквизитов. В целях оптимизации объема базы данных механизмы БСП (Библиотеки стандартных подсистем) используют принцип разреженного хранения данных. Это означает, что если значение реквизита соответствует значению «по умолчанию» для его типа (для типа Булево это Ложь, для ссылочных типов — ПустаяСсылка), то строка в табличной части ДополнительныеРеквизиты просто не создается.

Выясним причину проблемы на примере типичного ошибочного запроса:


ВЫБРАТЬ
    ОтчетКомиссионера.Ссылка КАК Ссылка
ИЗ
    Документ.ОтчетКомиссионера КАК ОтчетКомиссионера
ГДЕ
    ОтчетКомиссионера.ДополнительныеРеквизиты.Свойство = &СвойствоВозвраты
    И ОтчетКомиссионера.ДополнительныеРеквизиты.Значение = &ЗначениеЛожь

В данном случае обращение через «точку» к табличной части ДополнительныеРеквизиты заставляет систему выполнять ВНУТРЕННЕЕ СОЕДИНЕНИЕ. Так как записи со значением Ложь физически не существует в таблице, условие ГДЕ отсекает все документы, у которых эта строка отсутствует. В результате мы видим только те документы, где значение явно заполнено как Истина.

Способ 1: Использование ЛЕВОГО СОЕДИНЕНИЯ и проверки на NULL

Рассмотрим самый распространенный и правильный метод решения проблемы. Нам необходимо принудительно соединить основную таблицу документов с таблицей дополнительных реквизитов, используя ЛЕВОЕ СОЕДИНЕНИЕ. При этом критически важно перенести условие по конкретному свойству (самому реквизиту) из блока ГДЕ в блок ПО (условие связи).

Разберем этот метод по шагам:

  1. Выбираем основную таблицу документов.
  2. Присоединяем таблицу дополнительных реквизитов по ссылке.
  3. В условии связи указываем конкретное свойство из ПланВидовХарактеристик.ДополнительныеРеквизитыИСведения.
  4. В блоке ГДЕ используем функцию ЕСТЬNULL, чтобы превратить отсутствие записи в логическую Ложь.

Посмотрим на пример правильного кода:


Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ
|	ОтчетКомиссионера.Ссылка КАК Ссылка
|ИЗ
|	Документ.ОтчетКомиссионера КАК ОтчетКомиссионера
|		ЛЕВОЕ СОЕДИНЕНИЕ Документ.ОтчетКомиссионера.ДополнительныеРеквизиты КАК ДопРек
|		ПО ДопРек.Ссылка = ОтчетКомиссионера.Ссылка
|			И ДопРек.Свойство = &СвойствоВозвраты
|ГДЕ
|	ОтчетКомиссионера.НомерВходящегоДокумента = &Накладная
|	И ЕСТЬNULL(ДопРек.Значение, ЛОЖЬ) = &НужноеЗначениеБулево";

Запрос.УстановитьПараметр("Накладная", НомерНакладной);
Запрос.УстановитьПараметр("СвойствоВозвраты", СсылкаНаСвойствоПВХ);
Запрос.УстановитьПараметр("НужноеЗначениеБулево", Ложь); // Здесь передаем Ложь

Результат = Запрос.Выполнить();

В этом примере, если строки в табличной части нет, ДопРек.Значение вернет NULL, который функция ЕСТЬNULL преобразует в ЛОЖЬ, и условие сработает корректно.

Способ 2: Инверсия поиска через временные таблицы

В некоторых случаях, когда документов очень много, использование ЛЕВОГО СОЕДИНЕНИЯ с ЕСТЬNULL может работать медленнее, чем ожидается. Проанализируем альтернативный вариант — поиск «от противного». Мы можем сначала найти все документы, у которых реквизит установлен в Истина, а затем исключить их из общего списка документов.

Рассмотрим структуру такого запроса:


ВЫБРАТЬ
    ОтчетКомиссионера.Ссылка КАК Ссылка
ПОМЕСТИТЬ ВТ_С_Истиной
ИЗ
    Документ.ОтчетКомиссионера.ДополнительныеРеквизиты КАК ДопРек
ГДЕ
    ДопРек.Свойство = &СвойствоВозвраты
    И ДопРек.Значение = ИСТИНА;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ОтчетКомиссионера.Ссылка
ИЗ
    Документ.ОтчетКомиссионера КАК ОтчетКомиссионера
ГДЕ
    ОтчетКомиссионера.НомерВходящегоДокумента = &Накладная
    И НЕ ОтчетКомиссионера.Ссылка В (ВЫБРАТЬ Ссылка ИЗ ВТ_С_Истиной)

Такой подход часто оказывается более производительным на огромных массивах данных, так как СУБД проще работать с индексом по существующим записям Истина, чем выполнять полное сканирование для поиска отсутствующих строк.

Важные нюансы и типичные ошибки

При реализации поиска по дополнительным реквизитам следует учитывать несколько технических моментов, которые могут привести к ошибкам в коде.

1. Ошибка использования конструкции ЗНАЧЕНИЕ()

Многие разработчики пытаются получить ссылку на дополнительный реквизит прямо в запросе через ЗНАЧЕНИЕ(ПланВидовХарактеристик.ДополнительныеРеквизитыИСведения.ИмяРеквизита). Важно помнить: эта конструкция работает только для предопределенных элементов, созданных в конфигураторе. Дополнительные реквизиты, созданные пользователем в режиме «1С:Предприятие», не являются предопределенными. Их нужно искать программно (например, по наименованию или уникальному идентификатору) и передавать в запрос через параметр.

2. Различие между «Ложь» и «Не установлено»

Если для вашей бизнес-логики критично отличать ситуацию, когда пользователь специально снял галочку, от ситуации, когда реквизит вообще никогда не заполнялся, тип Булево вам не подойдет. В этом случае рекомендуется использовать тип Дополнительное значение и создать два элемента: «Да» и «Нет». Тогда в базе всегда будет присутствовать запись, и вы сможете использовать обычное внутреннее соединение.

3. Имена свойств

Метод НайтиПоНаименованию() является небезопасным, так как пользователь может изменить название реквизита в интерфейсе. Лучше использовать поиск по внутреннему имени (если оно заполнено программно) или хранить ссылку на свойство в настройках/параметрах системы.

Резюме

Проанализировав проблему, мы пришли к выводу, что отсутствие записи в таблице дополнительных реквизитов — это штатное поведение платформы 1С для экономии ресурсов. Чтобы ваш запрос всегда корректно находил документы со значением Ложь, всегда используйте ЛЕВОЕ СОЕДИНЕНИЕ с условием по свойству в секции ПО и обработкой NULL в секции ГДЕ.

← На главную