Как настроить быструю сортировку в динамическом списке с группировками в 1С

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

В разработке на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ограничением: как только в тексте запроса динамического списка появляется оператор ГРУППИРОВАТЬ ПО (GROUP BY), стандартная возможность «быстрой сортировки» нажатием на заголовок колонки бесследно исчезает. Это происходит из-за того, что платформа не всегда может однозначно сопоставить строку сгруппированного результата с конкретной записью основной таблицы базы данных для эффективного построения SQL-запроса «на лету».

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

Причина возникновения проблемы

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

Однако использование ГРУППИРОВАТЬ ПО на верхнем уровне запроса превращает выборку в агрегированные данные. В этом случае механизм динамического считывания (курсор СУБД) не может эффективно применять смещения и фильтры по внутренним идентификаторам (UID) записей. В результате платформа отключает интерактивные функции, такие как сортировка кликом по заголовку, чтобы предотвратить катастрофическое падение производительности при попытке отсортировать сотни тысяч сгруппированных строк.

Способ 1. Программная реализация сортировки

Если нам критично сохранить группировку именно в тексте запроса, мы можем реализовать механизм управления порядком программно. Поскольку стандартного события ПриНажатииНаЗаголовокКолонки не существует, этот метод обычно применяется при нажатии на специально созданные кнопки или через пункты контекстного меню.

Рассмотрим код процедуры, которая позволяет принудительно установить направление сортировки для динамического списка. Проанализируем пример:


&НаКлиенте
Процедура СортироватьСписокПоПолю(Список, ПолеНаименование, Направление = "Возр")
    
    // Очищаем текущие настройки порядка, чтобы не накапливать условия
    Список.Порядок.Элементы.Очистить();
    
    // Добавляем новый элемент порядка в коллекцию компоновки данных
    НовыйПорядок = Список.Порядок.Элементы.Добавить(Тип("ЭлементПорядкаКомпоновкиДанных"));
    
    // Указываем поле, по которому будет производиться сортировка
    НовыйПорядок.Поле = Новый ПолеКомпоновкиДанных(ПолеНаименование);
    
    // Устанавливаем режим отображения и использование
    НовыйПорядок.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Обычный;
    НовыйПорядок.Использование = Истина;
    
    // Выбираем направление сортировки
    Если Направление = "Возр" Тогда
        НовыйПорядок.ТипУпорядочивания = НаправлениеСортировкиКомпоновкиДанных.Возр;
    Иначе
        НовыйПорядок.ТипУпорядочивания = НаправлениеСортировкиКомпоновкиДанных.Убыв;
    КонецЕсли;
    
КонецПроцедуры

Этот метод работает даже в тех случаях, когда интерактивная сортировка заблокирована. Мы напрямую манипулируем объектом КомпоновщикНастроек, который лежит в основе динамического списка. Выясним важный нюанс: при таком подходе важно, чтобы поле ПолеНаименование было доступно в выбранных полях запроса и не являлось сложным вычисляемым выражением, не имеющим индекса в СУБД.

Способ 2. Использование вложенных запросов (Обход ограничений)

Посмотрим на более изящный способ, который позволяет «обмануть» платформу и сохранить интерактивность. Как показывает практика, платформа блокирует сортировку только тогда, когда ГРУППИРОВАТЬ ПО находится в самом внешнем запросе.

Выясним логику обхода. Мы можем поместить весь наш сложный запрос с группировками во вложенный запрос, а на верхнем уровне просто выбрать из него данные, соединив их (при необходимости) с основной таблицей. Рассмотрим примерную структуру такого запроса:


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

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

Способ 3. Перенос группировки в настройки списка

Проанализируем ситуацию: а действительно ли нам нужна группировка в самом SQL-запросе? Часто программисты используют GROUP BY для визуального разделения данных (например, группировка заказов по контрагентам). Но в динамическом списке 1С есть встроенный механизм иерархического отображения.

Разберем шаги для реализации этого метода:

  1. Удаляем оператор ГРУППИРОВАТЬ ПО из текста запроса.
  2. В конфигураторе открываем свойства динамического списка, заходим в «Настройка списка».
  3. Переходим на закладку «Группировка».
  4. Добавляем нужное поле (например, Контрагент).

Преимущество этого метода: данные из базы выбираются линейно (что очень быстро), а дерево группировок строит сам интерфейс 1С. При этом быстрая сортировка внутри групп по заголовкам колонок продолжает работать идеально. Это наиболее «правильный» путь с точки зрения архитектуры платформы 8.3.

Важные замечания по производительности

При реализации любого из этих решений, рассмотрим критические факторы, влияющие на скорость работы:

Подводя итог, можно сказать: если вам нужна быстрая сортировка в списке с итогами, лучше всего использовать Способ 3 (группировка средствами настроек). Если же группировка в запросе неустранима (например, для вычисления сложных агрегатов), используйте Способ 2 с вложенными запросами, сохраняя основную таблицу на верхнем уровне.

← На главную