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