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

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

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

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

Базовый запрос: использование оператора В ИЕРАРХИИ

Проанализируем ситуацию, описанную в теме: у нас есть иерархический справочник, и требуется получить все подчиненные элементы для выбранной ветки (например, найти конкретные свойства или элементы, расположенные ниже определенного родительского узла). Для этого не нужно писать собственные алгоритмы рекурсии. В языке запросов 1С существует специальный оператор сравнения В ИЕРАРХИИ.

Посмотрим на пример базового запроса:


ВЫБРАТЬ
    Игрушки.Ссылка КАК Ссылка,
    Игрушки.Наименование КАК Наименование
ИЗ
    Справочник.Игрушки КАК Игрушки
ГДЕ
    Игрушки.Ссылка В ИЕРАРХИИ(&РодительскийУзел)

В параметр &РодительскийУзел передается ссылка на элемент или группу, начиная с которой требуется спуститься вниз по дереву. Оператор В ИЕРАРХИИ автоматически обойдет всю ветку на любую глубину и вернет все дочерние записи.

Исключение исходного узла из результата

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

Выясним причину и устраним ее с помощью простого дополнительного условия в секции ГДЕ:


ВЫБРАТЬ
    Игрушки.Ссылка КАК Ссылка,
    Игрушки.Наименование КАК Наименование
ИЗ
    Справочник.Игрушки КАК Игрушки
ГДЕ
    Игрушки.Ссылка В ИЕРАРХИИ(&РодительскийУзел)
    И Игрушки.Ссылка <> &РодительскийУзел

Если в качестве параметра &СписокРодителей передается массив или список значений, исключение исходных узлов выполняется через отрицание списка: И НЕ Игрушки.Ссылка В (&СписокРодителей).

Учет типа иерархии и отсечение групп

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

  1. Иерархия групп и элементов: в таких справочниках родителями могут выступать только специальные элементы-папки (группы). При выполнении запроса с В ИЕРАРХИИ платформа вернет и вложенные группы, и конечные элементы. Если нам требуются только конкретные конечные элементы (без промежуточных папок), необходимо явно добавить проверку стандартного реквизита: И НЕ Игрушки.ЭтоГруппа (или И Игрушки.ЭтоГруппа = ЛОЖЬ).
  2. Иерархия элементов: в таких справочниках папок нет вовсе, любой элемент может являться родителем для другого элемента. В этом случае реквизит ЭтоГруппа отсутствует, а проверка не требуется.

Посмотрим на пример комплексного запроса, где мы выбираем только конечные элементы ветки с наложением дополнительного фильтра (например, по наименованию или реквизиту):


ВЫБРАТЬ
    Игрушки.Ссылка КАК Ссылка,
    Игрушки.Наименование КАК Наименование
ИЗ
    Справочник.Игрушки КАК Игрушки
ГДЕ
    Игрушки.Ссылка В ИЕРАРХИИ(&РодительскийУзел)
    И Игрушки.Ссылка <> &РодительскийУзел
    И НЕ Игрушки.ЭтоГруппа
    И Игрушки.Наименование ПОДОБНО &МаскаПоиска

Выборка только непосредственных потомков (первый уровень)

Рассмотрим подробнее сценарий, когда не требуется спускаться на всю глубину дерева, а нужны только прямые потомки первого уровня. Использовать конструкцию В ИЕРАРХИИ в таком случае избыточно и неэффективно с точки зрения производительности.

Для выборки только прямых детей достаточно проверить стандартный реквизит Родитель через прямое равенство:


ВЫБРАТЬ
    Игрушки.Ссылка КАК Ссылка,
    Игрушки.Наименование КАК Наименование
ИЗ
    Справочник.Игрушки КАК Игрушки
ГДЕ
    Игрушки.Родитель = &РодительскийУзел
    И НЕ Игрушки.ЭтоГруппа

Вопросы производительности и рекомендации

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

  1. Трансляция в SQL: оператор В ИЕРАРХИИ транслируется платформой в рекурсивные табличные выражения или сложные соединения на стороне СУБД. На справочниках с сотнями тысяч элементов и большой глубиной вложенности такие запросы могут выполняться относительно тяжело.
  2. Передача списков: если требуется проверить вхождение в иерархию для большого массива родительских узлов, не передавайте огромный массив напрямую в параметр. Значительно эффективнее сначала загрузить массив во временную таблицу и затем использовать условие Ссылка В ИЕРАРХИИ (ВЫБРАТЬ Ссылка ИЗ ВТ_Родители).
  3. Индексация реквизитов: любые дополнительные поля, по которым накладываются условия в секции ГДЕ вместе с иерархией, должны иметь свойство «Индексировать» в метаданных, чтобы оптимизатор СУБД мог эффективно сузить выборку.
  4. Отказ от объектной рекурсии: метод объектной модели Справочники.Игрушки.Выбрать(Родитель) выбирает подчиненные элементы только одного уровня. Попытка организовать рекурсивный обход дерева программным кодом приводит к сотням отдельных запросов к СУБД (проблема N+1), поэтому для любых массовых выборок следует использовать исключительно единый запрос с оператором В ИЕРАРХИИ.
← На главную