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