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

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

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

Стандартная конструкция УПОРЯДОЧИТЬ ПО Ссылка ИЕРАРХИЯ отлично строит само дерево, но зачастую игнорирует дополнительные поля сортировки, указанные после нее. Разберем детально, почему так происходит и как добиться желаемого результата несколькими способами.

Проблема использования «УПОРЯДОЧИТЬ ПО ... ИЕРАРХИЯ»

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

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


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

В данном случае платформа 1С сначала выполняет построение иерархического дерева по полю Ссылка. Внутренние механизмы системы при этом могут «забывать» о втором поле сортировки СортировкаНаборКомплект, так как приоритетом является сохранение связей «Родитель-Ребенок». В итоге мы получаем дерево, где элементы внутри папок перемешаны или отсортированы только по внутреннему идентификатору (GUID).

Способ 1. Использование конструкции «ИТОГИ ПО ... ТОЛЬКО ИЕРАРХИЯ»

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

Посмотрим на пример реализации:


ВЫБРАТЬ
    Номенклатура.Ссылка КАК Ссылка,
    Номенклатура.ЭтоГруппа КАК ЭтоГруппа,
    Номенклатура.Наименование КАК Наименование,
    ВЫБОР
        КОГДА Номенклатура.ВидНоменклатуры = &НаборКомплект
            ТОГДА 1
        ИНАЧЕ 0
    КОНЕЦ КАК СортировкаНаборКомплект
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ГДЕ
    Номенклатура.Ссылка В ИЕРАРХИИ(&ГруппаНоменклатуры)
УПОРЯДОЧИТЬ ПО
    ЭтоГруппа УБЫВ,
    СортировкаНаборКомплект УБЫВ,
    Наименование
ИТОГИ ПО
    Ссылка ТОЛЬКО ИЕРАРХИЯ

Важные моменты этого решения:

  1. Поле ЭтоГруппа УБЫВ: Мы ставим его первым в сортировке. Так как Истина (1) больше Ложи (0), при сортировке УБЫВ папки всегда будут оказываться выше элементов внутри одного уровня.
  2. СортировкаНаборКомплект УБЫВ: Это наше целевое поле. Оно обеспечит нахождение «наборов» вверху списка под папками.
  3. Обход результата: Чтобы увидеть результат именно в виде дерева с правильной сортировкой, в коде 1С необходимо использовать метод Выбрать(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией).

Способ 2. Применение «АВТОУПОРЯДОЧИВАНИЕ»

Если нам достаточно стандартной сортировки (например, по наименованию или коду) внутри иерархии, можно воспользоваться ключевым словом АВТОУПОРЯДОЧИВАНИЕ. Оно заставляет систему автоматически добавлять поля основного представления объекта в конец секции упорядочивания.

Выясним, как это выглядит в коде:


УПОРЯДОЧИТЬ ПО
    Номенклатура.Ссылка ИЕРАРХИЯ
АВТОУПОРЯДОЧИВАНИЕ

Проанализируем ситуацию: этот метод прост, но он менее гибкий. Он не позволит вам вынести «наборы» вперед, если их наименования начинаются на последние буквы алфавита. Однако для обычной задачи «построить дерево и внутри отсортировать по алфавиту» — это кратчайший путь.

Способ 3. Иерархия через левое соединение (для сложных случаев)

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

Рассмотрим логику запроса:


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

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

Рекомендация по использованию СКД

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

  1. В запросе вы пишете обычную «плоскую» выборку без ИТОГИ и ИЕРАРХИЯ.
  2. В настройках структуры СКД добавляете группировку Номенклатура и в поле «Тип группировки» выбираете Иерархия.
  3. В настройках сортировки этой группировки указываете ваши поля: СортировкаНаборКомплект (Убыв) и Наименование (Возр).

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

Подводя итог, можно сказать: если вы работаете с «чистым» запросом в коде — используйте Способ №1 (Итоги по иерархии). Если вы делаете отчет — доверьте построение дерева компоновке данных.

← На главную