Разработка и Конфигурация · 11 мин
Как получить уровень справочника в запросе 1С
Разбираем, как получить уровень иерархии справочника в запросе 1С: функция Уровень(), ключевое слово УРОВЕНЬ ИЕРАРХИИ, итоги по иерархии, примеры кода и типичные ошибки.
Иерархические справочники — Номенклатура, Контрагенты, Подразделения — часто требуют определить, на какой глубине находится элемент: является ли он группой верхнего уровня или вложен на несколько уровней вглубь. В языке запросов 1С для этого есть два разных механизма: функция Уровень() и ключевое слово УРОВЕНЬ ИЕРАРХИИ в секции итогов. Они работают по-разному, и выбор зависит от задачи.
Функция Уровень() применяется к ссылке на элемент иерархического справочника и возвращает число: 1 для элементов верхнего уровня, 2 для вложенных в них и так далее. Слово УРОВЕНЬ ИЕРАРХИИ используется только в конструкции ИТОГИ ... ПО ... ИЕРАРХИЯ и показывает уровень записи внутри иерархического результата запроса. Путать их нельзя — синтаксис и область применения разные.
Ниже разобраны оба способа с готовыми примерами запросов, ограничениями платформы и типичными ошибками, которые приводят к ошибкам компиляции или неверным данным.
Как устроена иерархия справочника и что считается уровнем
Справочник в 1С становится иерархическим, если в конфигураторе у него включено свойство «Иерархический». Иерархия бывает двух видов: «Список групп и элементов» (группы — это папки, элементы лежат внутри) и «Элементы» (любой элемент может быть родителем другого). В обоих случаях у каждого элемента есть поле Родитель — ссылка на элемент-родителя.
Уровень — это глубина вложенности элемента в дерево. Элементы без родителя (родитель — пустая ссылка) имеют уровень 1. Их дочерние элементы — уровень 2, и так далее. Максимальная глубина не ограничена жёстко платформой, но на практике редко превышает 5–7 уровней.
Важно понимать: уровень не хранится в базе как отдельный реквизит. Платформа вычисляет его динамически, проходя по цепочке ссылок Родитель. Поэтому запросы с вычислением уровня на больших справочниках требуют внимания к производительности.
Получение уровня функцией Уровень() в запросе
Самый прямой способ — встроенная функция языка запросов Уровень(<Ссылка>). Она принимает ссылку на элемент иерархического справочника и возвращает число — глубину элемента. Функцию можно использовать в секциях ВЫБРАТЬ, ГДЕ и УПОРЯДОЧИТЬ ПО.
Пример запроса, выводящего элементы справочника «Номенклатура» с их уровнями:
ВЫБРАТЬ
Номенклатура.Ссылка КАК Ссылка,
Номенклатура.Наименование КАК Наименование,
Номенклатура.Родитель КАК Родитель,
Уровень(Номенклатура.Ссылка) КАК Уровень
ИЗ
Справочник.Номенклатура КАК Номенклатура
УПОРЯДОЧИТЬ ПО
Уровень
Функция работает и в условии отбора. Например, выбрать только элементы верхнего уровня (группы и элементы без родителя):
ВЫБРАТЬ
Номенклатура.Ссылка КАК Ссылка,
Номенклатура.Наименование КАК Наименование
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
Уровень(Номенклатура.Ссылка) = 1
Аналогично можно отобрать элементы «не глубже третьего уровня»: ГДЕ Уровень(Номенклатура.Ссылка) <= 3. Это удобно для выгрузок, где нужно ограничить глубину дерева.
УРОВЕНЬ ИЕРАРХИИ в итогах по иерархии
Второй механизм связан с иерархическими итогами. Когда запрос строит результат с группировкой ИТОГИ ПО ... ИЕРАРХИЯ, платформа формирует дерево записей, и для каждой записи можно получить её уровень в этом дереве через выражение УРОВЕНЬ ИЕРАРХИИ.
ВЫБРАТЬ
Номенклатура.Ссылка КАК Ссылка,
Номенклатура.Наименование КАК Наименование,
1 КАК Количество
ИЗ
Справочник.Номенклатура КАК Номенклатура
ИТОГИ
СУММА(Количество),
УРОВЕНЬ ИЕРАРХИИ КАК Уровень
ПО
Ссылка ИЕРАРХИЯ
В секции ИТОГИ после ключевого слова задаётся выражение УРОВЕНЬ ИЕРАРХИИ с псевдонимом. В результате запроса у каждой строки появится поле с номером уровня внутри построенного дерева. Это полезно при обходе результата в коде, когда нужно отрисовать дерево с отступами или обработать только группы определённой глубины.
Обход такого результата выполняется через Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией), и на каждой итерации доступно поле Уровень, объявленное в итогах. Отличие от функции Уровень() в том, что здесь уровень отражает структуру именно результата запроса, а не полную глубину элемента в справочнике — если исходная выборка отфильтрована, нумерация уровней в дереве итогов может отличаться от «абсолютной» глубины элемента.
Практические сценарии использования
Отбор только групп или только элементов
Уровень сам по себе не отвечает на вопрос «группа это или элемент» — для этого есть поле ЭтоГруппа (для иерархии вида «группы и элементы»). Но комбинация уровня и признака группы решает типовую задачу: выбрать группы первого уровня для дерева на форме.
ВЫБРАТЬ
Номенклатура.Ссылка КАК Ссылка,
Номенклатура.Наименование КАК Наименование
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
Номенклатура.ЭтоГруппа
И Уровень(Номенклатура.Ссылка) = 1
И НЕ Номенклатура.ПометкаУдаления
Вывод дерева с отступами в отчёте
В отчётах на СКД или при программном выводе уровень используют для визуального отступа: чем глубже элемент, тем больше отступ. Для этого достаточно включить Уровень(Ссылка) в поля запроса и использовать значение при формировании строки табличного документа.
Проверка глубины при обмене данными
При выгрузке справочников во внешние системы часто действует ограничение на глубину дерева категорий. Запрос с условием Уровень(Ссылка) <= N отсекает лишние уровни до передачи данных, а запрос с Уровень(Ссылка) > N находит элементы, нарушающие ограничение, — их можно перераспределить вручную.
- 1Убедитесь, что справочник иерархический (свойство «Иерархический» в конфигураторе)
- 2Откройте консоль запросов или конструктор запроса в модуле
- 3Добавьте в секцию ВЫБРАТЬ выражение Уровень(Таблица.Ссылка) КАК Уровень
- 4При необходимости добавьте отбор ГДЕ Уровень(Таблица.Ссылка) = нужное значение
- 5Выполните запрос и проверьте, что верхние элементы имеют уровень 1
Производительность и ограничения
Функция Уровень() вычисляется платформой обходом цепочки родителей. На справочниках с десятками тысяч элементов и глубокой иерархией запрос с вычислением уровня для каждой строки может выполняться заметно дольше обычной выборки. Если уровень нужен только для отбора, а не для вывода, оцените, нельзя ли заменить условие более дешёвым.
Частая альтернатива для верхнего уровня — сравнение родителя с пустой ссылкой: ГДЕ Номенклатура.Родитель = ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка). Такое условие не требует вычисления глубины и работает быстрее, чем Уровень(Ссылка) = 1, хотя результат идентичен.
Ещё одно ограничение: Уровень() нельзя применять к произвольным выражениям и соединениям — только к полю-ссылке на иерархический справочник. В запросах с объединениями и временными таблицами проверяйте, что тип поля не «размылся» и остался ссылкой на конкретный справочник.
Сравнение способов получения уровня
Подходит для отбора, сортировки и вывода абсолютной глубины элемента. Ограничение: только ссылки на иерархические справочники, вычисляется для каждой строки
Подходит при обходе дерева результата, построенного через ИТОГИ ПО ... ИЕРАРХИЯ. Ограничение: отражает структуру результата, а не полную глубину в справочнике
Самый быстрый способ найти элементы верхнего уровня. Ограничение: работает только для первого уровня, глубже не применить
Проверка результата и типичные ошибки
После выполнения запроса проверьте несколько контрольных точек. Элементы без родителя должны иметь уровень 1 — если у них выводится 0 или NULL, скорее всего, запрос обращается не к тому полю или справочник неиерархический. Дочерние элементы одной группы должны иметь одинаковый уровень — расхождение указывает на ошибку в данных (например, циклические ссылки в родителях, хотя платформа обычно их блокирует).
Как проверить результат
Равен 1
0, NULL или разные значения — проверьте тип поля и иерархичность справочника
Одинаковый у всех, на 1 больше родителя
Различается — возможны повреждённые ссылки на родителей
Сопоставима с обычной выборкой по справочнику
Запрос «зависает» на большом справочнике — замените отбор по уровню сравнением родителя
Отдельно отметим работу в консоли запросов: если вы отлаживаете запрос с УРОВЕНЬ ИЕРАРХИИ, в табличном результате консоли поле уровня может отображаться только при выводе с группировками. При плоском выводе строки итогов скрываются, и создаётся ложное впечатление, что механизм не работает.
FAQ
Можно ли получить уровень справочника без запроса, в коде?
Да, но платформа не даёт прямого свойства «Уровень» у объекта справочника. В коде уровень вычисляют циклом по родителям: пока Родитель не пустой, увеличивать счётчик и переходить к Родитель.Родитель. Для разовой проверки это допустимо, но в цикле по тысячам элементов такой подход порождает обращения к базе на каждом шаге — запрос с Уровень() эффективнее.
Почему Уровень() возвращает 1 у всех элементов?
Наиболее вероятная причина — справочник настроен как иерархический, но элементы реально не имеют родителей (плоская структура). Реже — запрос обращается к неиерархическому справочнику, где функция формально допустима, но всегда даёт 1. Проверьте поле Родитель у нескольких элементов.
Работает ли Уровень() в СКД (системе компоновки данных)?
Да, функция доступна в запросе набора данных СКД наравне с обычными запросами. Дополнительно в СКД иерархию часто выводят через настройку группировки с типом «Иерархия» — тогда уровень вложенности виден визуально без вычисления в запросе.
Как выбрать элементы строго определённого уровня, например только третьего?
Добавьте условие ГДЕ Уровень(Справочник.Ссылка) = 3. Учтите, что при этом элементы первого и второго уровней в выборку не попадут. Если нужны элементы третьего уровня вместе с их родителями для построения дерева, используйте ИТОГИ ПО Ссылка ИЕРАРХИЯ с отбором в исходной выборке.
Есть ли ограничение на максимальную глубину иерархии?
Жёсткого документированного ограничения платформа не устанавливает, однако глубокая иерархия увеличивает стоимость вычисления уровня и замедляет иерархические итоги. На практике структуры глубже 7–10 уровней считаются признаком неудачного проектирования и усложняют отчёты.
Чем УРОВЕНЬ ИЕРАРХИИ отличается от УРОВЕНЬ() в итогах?
УРОВЕНЬ() (функция в итогах) показывает уровень группировки в обычных итогах ПО полю, а УРОВЕНЬ ИЕРАРХИИ — уровень записи внутри иерархического дерева, построенного по ссылке. Для справочников с иерархией элементов применяется именно второй вариант вместе с конструкцией ПО Ссылка ИЕРАРХИЯ.
Что важно запомнить
Абсолютную глубину элемента даёт функция Уровень(Ссылка) — верхний уровень равен 1. Уровень строки в дереве результата даёт УРОВЕНЬ ИЕРАРХИИ в секции ИТОГИ ПО ... ИЕРАРХИЯ. Для отбора элементов верхнего уровня быстрее сравнить родителя с пустой ссылкой. Оба механизма работают только с иерархическими справочниками.