Как работает иерархическая сортировка (УПОРЯДОЧИТЬ ПО ... ИЕРАРХИЯ) в запросах 1С при использовании нескольких полей?

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

При разработке отчетов и обработок в системе «1С:Предприятие 8» часто возникает необходимость вывести данные иерархического справочника (например, Номенклатуры или Контрагентов) в удобном для пользователя виде. Если нам нужно, чтобы подчиненные элементы (строки-дети) располагались строго под своими родительскими группами, мы используем ключевое слово ИЕРАРХИЯ в секции УПОРЯДОЧИТЬ ПО. Однако, когда дело доходит до сортировки по нескольким полям одновременно, логика работы платформы становится неочевидной. Разберем детально, как устроен этот алгоритм «под капотом», и как ведут себя различные комбинации полей при упорядочивании.

Что происходит на техническом уровне (СУБД vs Сервер приложений)

Для начала проанализируем, как этот механизм реализован технически. В классическом языке SQL, который используют СУБД (MS SQL Server, PostgreSQL, Oracle), нет встроенного оператора ИЕРАРХИЯ в конструкции ORDER BY. СУБД возвращают плоские таблицы и умеют сортировать их только линейно.

Когда мы пишем запрос с использованием ключевого слова ИЕРАРХИЯ, происходит следующее:

  1. СУБД выполняет выборку данных без учета иерархической подчиненности, выполняя лишь стандартную линейную сортировку.
  2. Полученный плоский набор данных передается на сервер приложений 1С.
  3. Сервер приложений 1С в оперативной памяти выполняет построение дерева «родитель-потомок» и осуществляет финальную иерархическую сортировку полученных строк.

Именно из-за этого возникает известный конфликт с ключевым словом ПЕРВЫЕ. Если мы попытаемся выбрать, например, ПЕРВЫЕ 10 элементов и упорядочить их по иерархии, СУБД сначала жестко обрежет выборку до 10 записей, а сервер приложений 1С попытается построить иерархию из того, что осталось. В результате дочерние элементы могут потерять своих родителей, а дерево окажется «разорванным».

Разбор сценариев многополевой сортировки

Рассмотрим детально, как платформа 1С интерпретирует различные варианты написания инструкции УПОРЯДОЧИТЬ ПО при наличии нескольких полей.

Вариант 1: УПОРЯДОЧИТЬ ПО Поле1 ИЕРАРХИЯ, Поле2

Рассмотрим пример запроса:


ВЫБРАТЬ
    Номенклатура.Ссылка КАК Ссылка,
    Номенклатура.Код КАК Код,
    Номенклатура.Наименование КАК Наименование
ИЗ
    Справочник.Номенклатура КАК Номенклатура
УПОРЯДОЧИТЬ ПО
    Ссылка ИЕРАРХИЯ,
    Код

Выясним, как платформа обрабатывает такую инструкцию. Алгоритм работает по следующим шагам:

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

Таким образом, мы получаем идеально выстроенное дерево, где на каждом уровне ветки отсортированы по коду.

Аналогично работает популярный методический прием для вывода папок выше элементов:


УПОРЯДОЧИТЬ ПО
    Номенклатура.ЭтоГруппа ИЕРАРХИЯ,
    Наименование

Здесь булево поле ЭтоГруппа не имеет физического родителя, поэтому платформа сначала группирует записи так, чтобы папки (значение ИСТИНА) шли выше элементов (значение ЛОЖЬ), а внутри этих групп выполняет алфавитную сортировку по полю Наименование.

Вариант 2: УПОРЯДОЧИТЬ ПО Поле1 ИЕРАРХИЯ, Поле2, Поле3

Возьмем выражение: Упорядочить по Наименование ИЕРАРХИЯ, Код (где сортировка идет по иерархическому справочнику).

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

Вариант 3: УПОРЯДОЧИТЬ ПО Поле1, Поле2 ИЕРАРХИЯ

А теперь проанализируем ситуацию, когда ключевое слово ИЕРАРХИЯ указано не у первого поля сортировки. Например:


УПОРЯДОЧИТЬ ПО
    Реквизит1,
    Ссылка ИЕРАРХИЯ

В этом случае поведение платформы кардинально меняется:

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

Важное предупреждение: Такой подход таит в себе серьезную проблему «сломанного дерева». Если родительская группа имеет одно значение Реквизит1, а подчиненный ей элемент — другое, они попадут в разные сегменты сортировки. В результате дочерний элемент потеряет визуальную связь со своим родителем в итоговом выводе, и иерархическая структура будет разрушена.

Если же мы используем конструкцию типа Упорядочить по Наименование, Код ИЕРАРХИЯ, то иерархия будет строиться только для вложенных подгрупп (без учета конечных элементов), а сортировка на каждом уровне будет осуществляться по коду, тогда как элементы верхнего уровня будут упорядочены по наименованию.

Ограничения и важные нюансы

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

Альтернативные и более производительные методы

Поскольку построение дерева в оперативной памяти сервера приложений — это ресурсоемкая операция, использование УПОРЯДОЧИТЬ ПО ... ИЕРАРХИЯ в тяжелых запросах по большим таблицам (свыше десятков тысяч элементов) может существенно снизить производительность системы. Рассмотрим профессиональные альтернативы.

1. Использование предложения ИТОГИ ПО ... ИЕРАРХИЯ

Вместо сортировки в секции УПОРЯДОЧИТЬ ПО мы можем использовать расчет итогов. Пример конструкции:


ВЫБРАТЬ
    Номенклатура.Ссылка КАК Ссылка,
    Номенклатура.Штрихкод КАК Штрихкод
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ИТОГИ ПО
    Ссылка ИЕРАРХИЯ

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


ВыборкаГруппировки = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);
Пока ВыборкаГруппировки.Следующий() Цикл
    // Здесь мы получаем доступ к родительским группам и можем обходить их элементы
КонецЦикла;

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

2. Использование Системы компоновки данных (СКД)

Если ваша задача — вывести иерархический список в отчет, настоятельно рекомендуется отказаться от сортировки ИЕРАРХИЯ непосредственно в тексте запроса. Вместо этого предоставьте построение дерева Системе компоновки данных.

В настройках структуры отчета СКД вместо обычной группировки добавьте группировку с типом «Иерархия» или «Иерархия групп и элементов». СКД компонует и выводит дерево гораздо быстрее, задействуя оптимизированные внутренние механизмы платформы, а также позволяет конечным пользователям гибко управлять сортировкой в пользовательских настройках без изменения схемы компоновки.

← На главную