К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как получить уровень справочника в запросе 1С

Разбираем, как получить уровень иерархии справочника в запросе 1С: функция Уровень(), ключевое слово УРОВЕНЬ ИЕРАРХИИ, итоги по иерархии, примеры кода и типичные ошибки.

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

Функция Уровень() применяется к ссылке на элемент иерархического справочника и возвращает число: 1 для элементов верхнего уровня, 2 для вложенных в них и так далее. Слово УРОВЕНЬ ИЕРАРХИИ используется только в конструкции ИТОГИ ... ПО ... ИЕРАРХИЯ и показывает уровень записи внутри иерархического результата запроса. Путать их нельзя — синтаксис и область применения разные.

Ниже разобраны оба способа с готовыми примерами запросов, ограничениями платформы и типичными ошибками, которые приводят к ошибкам компиляции или неверным данным.

Как устроена иерархия справочника и что считается уровнем

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

Уровень — это глубина вложенности элемента в дерево. Элементы без родителя (родитель — пустая ссылка) имеют уровень 1. Их дочерние элементы — уровень 2, и так далее. Максимальная глубина не ограничена жёстко платформой, но на практике редко превышает 5–7 уровней.

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

Получение уровня функцией Уровень() в запросе

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

Пример запроса, выводящего элементы справочника «Номенклатура» с их уровнями:

ВЫБРАТЬ

Номенклатура.Ссылка КАК Ссылка,

Номенклатура.Наименование КАК Наименование,

Номенклатура.Родитель КАК Родитель,

Уровень(Номенклатура.Ссылка) КАК Уровень

ИЗ

Справочник.Номенклатура КАК Номенклатура

УПОРЯДОЧИТЬ ПО

Уровень

Функция работает и в условии отбора. Например, выбрать только элементы верхнего уровня (группы и элементы без родителя):

ВЫБРАТЬ

Номенклатура.Ссылка КАК Ссылка,

Номенклатура.Наименование КАК Наименование

ИЗ

Справочник.Номенклатура КАК Номенклатура

ГДЕ

Уровень(Номенклатура.Ссылка) = 1

Аналогично можно отобрать элементы «не глубже третьего уровня»: ГДЕ Уровень(Номенклатура.Ссылка) <= 3. Это удобно для выгрузок, где нужно ограничить глубину дерева.

УРОВЕНЬ ИЕРАРХИИ в итогах по иерархии

Второй механизм связан с иерархическими итогами. Когда запрос строит результат с группировкой ИТОГИ ПО ... ИЕРАРХИЯ, платформа формирует дерево записей, и для каждой записи можно получить её уровень в этом дереве через выражение УРОВЕНЬ ИЕРАРХИИ.

ВЫБРАТЬ

Номенклатура.Ссылка КАК Ссылка,

Номенклатура.Наименование КАК Наименование,

1 КАК Количество

ИЗ

Справочник.Номенклатура КАК Номенклатура

ИТОГИ

СУММА(Количество),

УРОВЕНЬ ИЕРАРХИИ КАК Уровень

ПО

Ссылка ИЕРАРХИЯ

В секции ИТОГИ после ключевого слова задаётся выражение УРОВЕНЬ ИЕРАРХИИ с псевдонимом. В результате запроса у каждой строки появится поле с номером уровня внутри построенного дерева. Это полезно при обходе результата в коде, когда нужно отрисовать дерево с отступами или обработать только группы определённой глубины.

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

Практические сценарии использования

Отбор только групп или только элементов

Уровень сам по себе не отвечает на вопрос «группа это или элемент» — для этого есть поле ЭтоГруппа (для иерархии вида «группы и элементы»). Но комбинация уровня и признака группы решает типовую задачу: выбрать группы первого уровня для дерева на форме.

ВЫБРАТЬ

Номенклатура.Ссылка КАК Ссылка,

Номенклатура.Наименование КАК Наименование

ИЗ

Справочник.Номенклатура КАК Номенклатура

ГДЕ

Номенклатура.ЭтоГруппа

И Уровень(Номенклатура.Ссылка) = 1

И НЕ Номенклатура.ПометкаУдаления

Вывод дерева с отступами в отчёте

В отчётах на СКД или при программном выводе уровень используют для визуального отступа: чем глубже элемент, тем больше отступ. Для этого достаточно включить Уровень(Ссылка) в поля запроса и использовать значение при формировании строки табличного документа.

Проверка глубины при обмене данными

При выгрузке справочников во внешние системы часто действует ограничение на глубину дерева категорий. Запрос с условием Уровень(Ссылка) <= N отсекает лишние уровни до передачи данных, а запрос с Уровень(Ссылка) > N находит элементы, нарушающие ограничение, — их можно перераспределить вручную.

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

Производительность и ограничения

Функция Уровень() вычисляется платформой обходом цепочки родителей. На справочниках с десятками тысяч элементов и глубокой иерархией запрос с вычислением уровня для каждой строки может выполняться заметно дольше обычной выборки. Если уровень нужен только для отбора, а не для вывода, оцените, нельзя ли заменить условие более дешёвым.

Частая альтернатива для верхнего уровня — сравнение родителя с пустой ссылкой: ГДЕ Номенклатура.Родитель = ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка). Такое условие не требует вычисления глубины и работает быстрее, чем Уровень(Ссылка) = 1, хотя результат идентичен.

Ещё одно ограничение: Уровень() нельзя применять к произвольным выражениям и соединениям — только к полю-ссылке на иерархический справочник. В запросах с объединениями и временными таблицами проверяйте, что тип поля не «размылся» и остался ссылкой на конкретный справочник.

Сравнение способов получения уровня

Функция Уровень(Ссылка)

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

УРОВЕНЬ ИЕРАРХИИ в ИТОГИ

Подходит при обходе дерева результата, построенного через ИТОГИ ПО ... ИЕРАРХИЯ. Ограничение: отражает структуру результата, а не полную глубину в справочнике

Сравнение Родителя с пустой ссылкой

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

Проверка результата и типичные ошибки

После выполнения запроса проверьте несколько контрольных точек. Элементы без родителя должны иметь уровень 1 — если у них выводится 0 или NULL, скорее всего, запрос обращается не к тому полю или справочник неиерархический. Дочерние элементы одной группы должны иметь одинаковый уровень — расхождение указывает на ошибку в данных (например, циклические ссылки в родителях, хотя платформа обычно их блокирует).

Контрольные точки

Как проверить результат

Уровень элементов без родителя
Норма

Равен 1

Тревожный признак

0, NULL или разные значения — проверьте тип поля и иерархичность справочника

Уровень дочерних элементов одной группы
Норма

Одинаковый у всех, на 1 больше родителя

Тревожный признак

Различается — возможны повреждённые ссылки на родителей

Скорость выполнения запроса
Норма

Сопоставима с обычной выборкой по справочнику

Тревожный признак

Запрос «зависает» на большом справочнике — замените отбор по уровню сравнением родителя

Типичные ошибки
01
Применение Уровень() к неиерархическому справочнику — запрос не компилируется, нужно проверить свойство «Иерархический» в конфигураторе
02
Использование УРОВЕНЬ ИЕРАРХИИ без секции ИТОГИ ПО ... ИЕРАРХИЯ — синтаксическая ошибка, выражение работает только в итогах
03
Ожидание, что уровень начинается с 0 — в 1С верхний уровень равен 1, условие «= 0» никогда ничего не вернёт
04
Отбор по уровню вместо сравнения родителя с пустой ссылкой на больших таблицах — лишняя нагрузка без выигрыша в результате
05
Путаница между уровнем элемента в справочнике и уровнем строки в иерархическом результате — при отфильтрованной выборке эти числа могут не совпадать

Отдельно отметим работу в консоли запросов: если вы отлаживаете запрос с УРОВЕНЬ ИЕРАРХИИ, в табличном результате консоли поле уровня может отображаться только при выводе с группировками. При плоском выводе строки итогов скрываются, и создаётся ложное впечатление, что механизм не работает.

FAQ

Можно ли получить уровень справочника без запроса, в коде?

Да, но платформа не даёт прямого свойства «Уровень» у объекта справочника. В коде уровень вычисляют циклом по родителям: пока Родитель не пустой, увеличивать счётчик и переходить к Родитель.Родитель. Для разовой проверки это допустимо, но в цикле по тысячам элементов такой подход порождает обращения к базе на каждом шаге — запрос с Уровень() эффективнее.

Почему Уровень() возвращает 1 у всех элементов?

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

Работает ли Уровень() в СКД (системе компоновки данных)?

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

Как выбрать элементы строго определённого уровня, например только третьего?

Добавьте условие ГДЕ Уровень(Справочник.Ссылка) = 3. Учтите, что при этом элементы первого и второго уровней в выборку не попадут. Если нужны элементы третьего уровня вместе с их родителями для построения дерева, используйте ИТОГИ ПО Ссылка ИЕРАРХИЯ с отбором в исходной выборке.

Есть ли ограничение на максимальную глубину иерархии?

Жёсткого документированного ограничения платформа не устанавливает, однако глубокая иерархия увеличивает стоимость вычисления уровня и замедляет иерархические итоги. На практике структуры глубже 7–10 уровней считаются признаком неудачного проектирования и усложняют отчёты.

Чем УРОВЕНЬ ИЕРАРХИИ отличается от УРОВЕНЬ() в итогах?

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

Итог

Что важно запомнить

Абсолютную глубину элемента даёт функция Уровень(Ссылка) — верхний уровень равен 1. Уровень строки в дереве результата даёт УРОВЕНЬ ИЕРАРХИИ в секции ИТОГИ ПО ... ИЕРАРХИЯ. Для отбора элементов верхнего уровня быстрее сравнить родителя с пустой ссылкой. Оба механизма работают только с иерархическими справочниками.