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