Почему в динамическом списке 1С недоступна сортировка по строковому полю и как это исправить?

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

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

Проанализируем типовой пример, в котором возникает эта проблема. Предположим, в запросе динамического списка источником выступает регистр сведений РеестрДокументов, а поле извлекается через обращение к реквизиту документа:


ВЫБРАТЬ
    РеестрДокументов.Ссылка КАК Ссылка,
    РеестрДокументов.НомерДокументаИБ КАК Номер,
    РеестрДокументов.ДатаДокументаИБ КАК Дата,
    РеестрДокументов.Ссылка.НомерБСО КАК НомерБСО
ИЗ
    РегистрСведений.РеестрДокументов КАК РеестрДокументов

Причины блокировки сортировки на уровне платформы и СУБД

Выясним причину такого поведения системы. Проблема кроется в сочетании двух факторов: особенностей работы с составными типами данных и ограничений систем управления базами данных (СУБД).

  1. Разыменование полей составного типа: если реквизит Ссылка имеет составной тип (например, может содержать ссылки на документы различных видов), то при обращении через точку РеестрДокументов.Ссылка.НомерБСО платформа 1С неявно генерирует левые соединения со всеми таблицами документов, входящими в этот тип. Если хотя бы в одном из этих документов реквизит НомерБСО имеет тип Строка неограниченной длины (или длина не задана жестко), результирующее поле запроса автоматически приобретает тип строки неограниченной длины.
  2. Ограничение СУБД на операцию ORDER BY: большинство современных СУБД (MS SQL Server, PostgreSQL, Oracle) на физическом уровне хранят строки неограниченной длины в виде LOB-структур (Large Object Data, TEXT, VARCHAR(MAX)) и не поддерживают сортировку по таким типам данных без явного преобразования. Платформа 1С:Предприятие отслеживает подобные типы и автоматически исключает их из списка полей, доступных для сортировки, чтобы предотвратить ошибки исполнения на сервере СУБД. При этом фильтрация (отбор) по таким полям остается доступной.

Рассмотрим по шагам практические способы решения этой задачи.

Способ 1. Явное приведение типа с помощью функции ВЫРАЗИТЬ

Самым быстрым и простым решением в запросе динамического списка является явное ограничение максимальной длины строки с помощью функции ВЫРАЗИТЬ(...). Это явно сообщает платформе и СУБД, что результат имеет фиксированную длину, после чего колонка становится доступной для сортировки.

Посмотрим на пример модификации текста запроса:


ВЫБРАТЬ
    РеестрДокументов.Ссылка КАК Ссылка,
    РеестрДокументов.НомерДокументаИБ КАК Номер,
    РеестрДокументов.ДатаДокументаИБ КАК Дата,
    ВЫРАЗИТЬ(РеестрДокументов.Ссылка.НомерБСО КАК СТРОКА(50)) КАК НомерБСО
ИЗ
    РегистрСведений.РеестрДокументов КАК РеестрДокументов

Указание типа СТРОКА(50) преобразует результирующее поле в строку фиксированной длины, что снимает ограничение СУБД и возвращает возможность сортировки как в настройках списка, так и по нажатию на заголовок колонки.

Способ 2. Ограничение типа через конструкцию ВЫБОР КОГДА ... ССЫЛКА

Если реквизит НомерБСО присутствует только в определенных видах документов, обращение через точку ко всем типам подряд создает избыточную нагрузку на СУБД. Оптимальнее проверить принадлежность ссылки к конкретному типу документа и явно привести тип:


ВЫБРАТЬ
    РеестрДокументов.Ссылка КАК Ссылка,
    РеестрДокументов.НомерДокументаИБ КАК Номер,
    ВЫБОР
        КОГДА РеестрДокументов.Ссылка ССЫЛКА Документ.РеализацияТоваровУслуг
            ТОГДА ВЫРАЗИТЬ(РеестрДокументов.Ссылка.НомерБСО КАК СТРОКА(50))
        КОГДА РеестрДокументов.Ссылка ССЫЛКА Документ.АктВыполненныхРабот
            ТОГДА ВЫРАЗИТЬ(РеестрДокументов.Ссылка.НомерБСО КАК СТРОКА(50))
        ИНАЧЕ ""
    КОНЕЦ КАК НомерБСО
ИЗ
    РегистрСведений.РеестрДокументов КАК РеестрДокументов

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

Способ 3. Замена разыменования на явное ЛЕВОЕ СОЕДИНЕНИЕ

Разыменование полей составного типа через точку является антипаттерном с точки зрения стандартов разработки 1С, так как приводит к множественным неконтролируемым соединениям в СУБД. Разберем более производительный вариант с явным левым соединением только с теми таблицами, где этот реквизит реально присутствует:


ВЫБРАТЬ
    РеестрДокументов.Ссылка КАК Ссылка,
    РеестрДокументов.НомерДокументаИБ КАК Номер,
    РеестрДокументов.ДатаДокументаИБ КАК Дата,
    ЕСТЬNULL(ВЫРАЗИТЬ(Реализация.НомерБСО КАК СТРОКА(50)), "") КАК НомерБСО
ИЗ
    РегистрСведений.РеестрДокументов КАК РеестрДокументов
    ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК Реализация
        ПО РеестрДокументов.Ссылка = Реализация.Ссылка

Использование явных соединений позволяет точно контролировать план выполнения запроса и исключает появление неограниченных строк в динамическом списке.

Способ 4. Исправление метаданных конфигурации

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

  1. Корректировка длины реквизита: найдем документ, у которого реквизит имеет неограниченную длину, и зададим ему фиксированную длину (например, 20 или 50 символов), если это допустимо бизнес-логикой.
  2. Денормализация данных: если по данному полю регулярно требуется поиск, отбор и сортировка в общих списках или реестрах документов, целесообразно добавить реквизит НомерБСО непосредственно в регистр сведений РеестрДокументов с фиксированной длиной строки и признаком индексирования. Это обеспечит максимальную производительность при работе с динамическим списком.
← На главную