Как настроить отбор в динамическом списке по реквизитам табличной части с использованием выражения ВЫБОР КОГДА?

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

При работе с динамическими списками в системе 1С:Предприятие 8.3 программисты часто сталкиваются с необходимостью вывода данных из табличных частей объектов непосредственно в основной список. Однако использование произвольных запросов с выборкой вложенных таблиц и применением логических условий ВЫБОР КОГДА часто приводит к ошибке: «Невозможно применить элемент отбора в наборе». В этой статье мы разберем, почему возникает это недоразумение и какими способами можно реализовать требуемый функционал.

Почему возникает ошибка при наложении отбора?

Проанализируем ситуацию: динамический список базируется на механизме Системы компоновки данных (СКД). Когда пользователь или программист устанавливает отбор по полю, которое находится внутри вложенной таблицы (табличной части) и при этом является вычисляемым (использует ВЫБОР), платформа пытается трансформировать исходный запрос для оптимизации. Ошибка возникает из-за того, что механизм компоновки не может корректно «пробросить» условие фильтрации внутрь вложенной выборки, если там присутствует сложная логика. Платформа не может гарантировать эффективное выполнение такого SQL-запроса, особенно на старых версиях платформы (например, 8.3.10).

Рассмотрим пример запроса, который вызывает проблему:


ВЫБРАТЬ
    СправочникКонтрагенты.Ссылка КАК Ссылка,
    СправочникКонтрагенты.Наименование КАК Наименование,
    СправочникКонтрагенты.СферыДеятельности.(
        Ссылка КАК Ссылка,
        ВЫБОР
            КОГДА &ЭтоМенеджерПоПродажам
                ТОГДА ЗНАЧЕНИЕ(Справочник.СферыДеятельности.ПустаяСсылка)
            ИНАЧЕ СправочникКонтрагенты.СферыДеятельности.СфераДеятельности
        КОНЕЦ КАК СфераДеятельности
    ) КАК СферыДеятельности
ИЗ
    Справочник.Контрагенты КАК СправочникКонтрагенты

Попытка установить отбор по полю СферыДеятельности.СфераДеятельности в данном случае приведет к аварийному завершению работы динамического списка.

Решение №1: Использование временных таблиц и синтаксиса СКД

Наиболее эффективный способ обойти ограничение — это использование временных таблиц в тексте запроса динамического списка. Современные версии платформы позволяют использовать временные таблицы, а синтаксис СКД дает возможность гибко управлять отборами. Мы можем вынести логику фильтрации по табличной части в отдельный блок.

Разберем этот метод по шагам. Сначала мы выбираем ссылки объектов, которые соответствуют критериям отбора по табличной части, и помещаем их во временную таблицу. Затем соединяем эту таблицу с основной выборкой.


ВЫБРАТЬ РАЗЛИЧНЫЕ
    КонтактнаяИнформация.Ссылка КАК Ссылка
ПОМЕСТИТЬ втОтфильтрованныеСсылки
ИЗ
    Справочник.Контрагенты.КонтактнаяИнформация КАК КонтактнаяИнформация
{ГДЕ
    КонтактнаяИнформация.Представление КАК ПредставлениеКонтактной}
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    СправочникКонтрагенты.Ссылка КАК Ссылка,
    СправочникКонтрагенты.Наименование КАК Наименование,
    СправочникКонтрагенты.ИНН КАК ИНН
ИЗ
    Справочник.Контрагенты КАК СправочникКонтрагенты
ГДЕ
    СправочникКонтрагенты.Ссылка В (ВЫБРАТЬ Ссылка ИЗ втОтфильтрованныеСсылки)

В данном примере конструкция {ГДЕ ...} является расширением языка запросов для СКД. Это позволяет системе автоматически подставлять условия отбора, установленные пользователем в настройках списка, непосредственно в запрос к табличной части. Это значительно повышает производительность и устраняет ошибку «невозможно применить элемент отбора».

Решение №2: Переход к «плоской» структуре запроса

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

Рассмотрим, как правильно реализовать такое соединение:

  1. Выполняем ЛЕВОЕ СОЕДИНЕНИЕ основной таблицы справочника с его табличной частью.
  2. Для полей, где требуется логика прав доступа (RLS) или скрытие данных, применяем ВЫБОР КОГДА.
  3. Если нужно избежать дублей, используем СГРУППИРОВАТЬ ПО или ВЫБРАТЬ РАЗЛИЧНЫЕ, но только если это не противоречит бизнес-логике отображения данных.

Важный момент: Если ваша задача связана с тонкой настройкой прав доступа (RLS), как в рассматриваемом случае с БСП, старайтесь выносить проверку параметров типа &ЭтоМенеджерПоПродажам на уровень параметров запроса динамического списка. Устанавливайте их программно при создании формы: Список.Параметры.УстановитьЗначениеПараметра("ЭтоМенеджерПоПродажам", ...);.

Решение №3: Программное управление текстом запроса

Если условия отображения данных для разных ролей (например, «Менеджер» и «Администратор») кардинально различаются, хорошим архитектурным решением будет программная подмена текста запроса динамического списка. В процедуре ПриСозданииНаСервере мы можем проанализировать роль текущего пользователя и установить упрощенный текст запроса для менеджеров, исключив из него проблемные вложенные таблицы и сложные выражения ВЫБОР.

Это не только решит проблему с отборами, но и положительно скажется на скорости открытия формы, так как системе не придется выполнять лишние проверки и соединения для тех пользователей, которым эти данные все равно недоступны.

Выяснив причину ограничения платформы, мы понимаем: для стабильной работы динамических списков следует избегать сочетания вложенных таблиц и вычисляемых полей в одном уровне запроса, если по ним планируется интерактивная фильтрация.

← На главную