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

Эта статья поможет разобраться, как именно формировать запросы для вывода уровней в 1С 8.3, какие нюансы учитывать при работе с иерархическими справочниками, и как избежать типичных ошибок. Мы рассмотрим не только базовый синтаксис, но и практические примеры для разных сценариев: от простого вывода дерева справочника до сложных отчетов с группировкой по уровням. Особое внимание уделим оптимизации запросов — это критично для больших баз данных, где неверный подход может привести к зависанию системы.

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

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

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

  • 🔹 По умолчанию запрос возвращает все записи справочника как единый набор, не анализируя поля Родитель или ЭтоГруппа.
  • 🔹 Функции УРОВЕНЬ() и ИЕРАРХИЯ() не применяются автоматически — их нужно явно указывать в тексте запроса.
  • 🔹 Без правильной настройки параметра ИерархическийПроход (например, Иерархия.РодительПотомки) запрос не будет рекурсивно обходить дерево.

Типичная ошибка — попытка получить уровни через поле Родитель вручную, например, с помощью конструкции ВЫБРАТЬ Справочник.Родитель КАК Уровень. Это не сработает, потому что:

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

Ещё один распространенный миф — что уровни можно получить через виртуальные таблицы. На самом деле виртуальные таблицы (например, Справочник.Номенклатура.Иерархия) лишь упрощают доступ к иерархическим данным, но не заменяют функции УРОВЕНЬ().

Функция УРОВЕНЬ(): синтаксис и базовые примеры

Функция УРОВЕНЬ() — основной инструмент для определения глубины вложенности элемента в иерархическом справочнике. Она возвращает числовое значение, где:

  • 📌 0 — корневой уровень (элементы без родителя).
  • 📌 1 — первый уровень вложенности (дочерние элементы корневых узлов).
  • 📌 2, 3, ... — последующие уровни.

Базовый синтаксис использования в запросе:

ВЫБРАТЬ

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

УРОВЕНЬ(Справочник.Номенклатура.Ссылка) КАК УровеньВложенности

ИЗ

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

ГДЕ

НЕ Справочник.ПометкаУдаления

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

УровеньВложенности, Ссылка.Наименование

Важные нюансы работы с УРОВЕНЬ():

  1. Требует указания иерархического прохода. Без параметра ИЕРАРХИЯ функция вернет NULL или некорректные значения.
  2. Работает только с полем Ссылка. Передача других полей (например, Наименование) приведет к ошибке.
  3. Зависит от прав доступа. Если у пользователя нет прав на просмотр родительских элементов, уровень может рассчитываться неверно.
📊 Какой тип иерархии вы чаще используете в 1С?
Иерархия элементов справочника
Иерархия групп и элементов
Планы видов характеристик
Другой вариант

Параметр ИЕРАРХИЯ: виды обхода дерева

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

Тип прохода Описание Пример использования
Иерархия.РодительПотомки Рекурсивно обходит все уровни, начиная с корневых элементов. Подходит для вывода полного дерева. Отчеты по номенклатуре с группировкой по категориям.
Иерархия.Потомки Возвращает только дочерние элементы для указанного родителя (без рекурсии). Вывод подкатегорий текущей группы в форме справочника.
Иерархия.Родители Возвращает цепочку родительских элементов для заданного узла. Построение "хлебных крошек" в интерфейсе.
Иерархия.ВладелецПотомки Аналогично РодительПотомки, но учитывает владельца справочника (актуально для подчиненных справочников). Работа с подчиненными справочниками в УТ 11.

Пример запроса с указанием прохода РодительПотомки:

ВЫБРАТЬ

Справочник.Контрагенты.Ссылка КАК Контрагент,

УРОВЕНЬ(Справочник.Контрагенты.Ссылка) КАК Уровень,

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

ИЗ

Справочник.Контрагенты КАК Справочник

ГДЕ

НЕ Справочник.ПометкаУдаления

И Справочник.ЭтоГруппа = ЛОЖЬ

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

Уровень,

Наименование

ИЕРАРХИЯ ПО

Справочник.Ссылка

ИЕРАРХИЧЕСКИЙ ПРОХОД РодительПотомки

⚠️ Внимание: Если в запросе используется параметр ИЕРАРХИЯ, но не указан ИЕРАРХИЧЕСКИЙ ПРОХОД, платформа по умолчанию применит РодительПотомки. Однако явное указание типа прохода делает код более читаемым и предсказуемым.
💡

Для ускорения работы запроса с иерархией добавьте условие ГДЕ Справочник.ЭтоГруппа = ЛОЖЬ, если вам нужны только элементы (не группы). Это сократит объем обрабатываемых данных.

Практические примеры: от простого к сложному

Пример 1: Вывод справочника с отступами по уровням

Частая задача — показать иерархический справочник в отчете или на форме с визуальными отступами. Для этого уровень вложенности можно преобразовать в строку с пробелами или символами:

ВЫБРАТЬ

ПОВТОР(" ", УРОВЕНЬ(Справочник.Номенклатура.Ссылка)) КАК Отступ,

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

УРОВЕНЬ(Справочник.Номенклатура.Ссылка) КАК Уровень

ИЗ

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

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

Уровень,

Наименование

ИЕРАРХИЯ ПО

Справочник.Ссылка

В результате поле Отступ будет содержать 4 пробела для каждого уровня вложенности, что позволит визуально структурировать данные в таблице.

Пример 2: Фильтрация по уровню вложенности

Иногда требуется получить элементы только определенного уровня, например, только группы второго уровня. Для этого используйте конструкцию ГДЕ УРОВЕНЬ(...) = N:

ВЫБРАТЬ

Справочник.Товары.Ссылка КАК Товар

ИЗ

Справочник.Товары КАК Справочник

ГДЕ

УРОВЕНЬ(Справочник.Товары.Ссылка) = 2

ИЕРАРХИЯ ПО

Справочник.Ссылка

Пример 3: Рекурсивный обход с ограничением по уровню

Если дерево справочника очень глубокое, можно ограничить количество уровней с помощью параметра УРОВЕНЬ ВЛОЖЕННОСТИ:

ВЫБРАТЬ

Справочник.Подразделения.Наименование КАК Подразделение

ИЗ

Справочник.Подразделения КАК Справочник

ИЕРАРХИЯ ПО

Справочник.Ссылка

УРОВЕНЬ ВЛОЖЕННОСТИ 3 // Ограничиваем до 3 уровней

Указан параметр ИЕРАРХИЯ ПО|Явно задан ИЕРАРХИЧЕСКИЙ ПРОХОД|Функция УРОВЕНЬ() применяется к полю Ссылка|Добавлена сортировка по уровню и наименованию|Учтена производительность для больших справочников-->

Оптимизация запросов с иерархией

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

  • Ограничивайте глубину обхода. Если вам не нужно все дерево, используйте УРОВЕНЬ ВЛОЖЕННОСТИ N.
  • Фильтруйте по группам. Если нужен только фрагмент дерева, добавьте условие ГДЕ Справочник.Родитель = &Группа.
  • Используйте виртуальные таблицы. Для сложных отчетов лучше обращаться к виртуальной таблице Справочник.Имя.Иерархия — она оптимизирована для таких задач.
  • Избегайте лишних полей. Включайте в выборку только необходимые колонки, особенно если запрос возвращает много строк.

Критическая ошибка многих разработчиков: использование функции УРОВЕНЬ() в подзапросах или объединениях (JOIN). Это приводит к многократному рекурсивному обходу дерева и может заблокировать базу. Вместо этого:

  1. Сначала получите все необходимые ссылки в основном запросе с указанием иерархии.
  2. Затем присоединяйте дополнительные данные через ЛЕВОЕ СОЕДИНЕНИЕ.

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

ВЫБРАТЬ

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

НоменклатураИерархия.Уровень КАК Уровень,

Цены.Цена КАК Цена

ИЗ

(ВЫБРАТЬ

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

УРОВЕНЬ(Справочник.Номенклатура.Ссылка) КАК Уровень

ИЗ

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

ИЕРАРХИЯ ПО

Справочник.Ссылка) КАК НоменклатураИерархия

ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних() КАК Цены

ПО НоменклатураИерархия.Ссылка = Цены.Номенклатура

Что делать, если запрос с иерархией выполняется слишком долго?

1. Проверьте, не загружаются ли лишние поля — оставьте только необходимые (Ссылка, Наименование, Уровень).

2. Разбейте запрос на два этапа: сначала получите иерархию, затем присоедините дополнительные данные.

3. Используйте временные таблицы для промежуточных результатов.

4. Если справочник очень большой (100 000+ элементов), рассмотрите вариант денормализации данных (хранение уровня в реквизите).

Типичные ошибки и как их избежать

Даже опытные разработчики иногда допускают ошибки при работе с иерархическими запросами. Вот наиболее распространённые проблемы и способы их решения:

Ошибка Причина Решение
Запрос возвращает NULL вместо уровней Не указан параметр ИЕРАРХИЯ ПО или неверное поле в функции УРОВЕНЬ(). Добавьте ИЕРАРХИЯ ПО Справочник.Ссылка и проверьте, что УРОВЕНЬ() применяется к полю Ссылка.
Уровни рассчитываются неверно (например, все элементы на уровне 0) Не указан ИЕРАРХИЧЕСКИЙ ПРОХОД или выбран не тот тип (например, Потомки вместо РодительПотомки). Явно укажите ИЕРАРХИЧЕСКИЙ ПРОХОД РодительПотомки.
Запрос выполняется слишком долго или падает с ошибкой Слишком глубокая рекурсия или отсутствие фильтров по группам. Ограничьте уровень вложенности или разбейте запрос на части.
В результатах отсутствуют дочерние элементы В условии ГДЕ есть фильтр, который исключает часть дерева (например, Справочник.ЭтоГруппа = ЛОЖЬ). Проверьте условия фильтрации или используйте ИЕРАРХИЯ ПО до применения ГДЕ.
⚠️ Внимание: Если в справочнике используются подчиненные справочники (например, в УТ 11), функция УРОВЕНЬ() может работать некорректно без указания владельца. В таких случаях используйте ИЕРАРХИЯ ПО Справочник.Ссылка ВЛАДЕЛЕЦ &Владелец.

Ещё одна распространённая проблема — несовпадение уровней при выводе в отчет. Например, в запросе уровни рассчитываются верно, но при выводе в табличный документ или СКД они отображаются некорректно. Это связано с тем, что:

  • 📉 В настройках отчета не включено группировка по уровню.
  • 📉 Используется неверный порядок сортировки (сначала должно идти поле Уровень, затем Наименование).
  • 📉 В СКД не настроено отображение иерархии (параметр Иерархия в настройках группы).

Работа с планами видов характеристик (ПВХ)

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

Пример запроса для вывода уровней в ПВХ:

ВЫБРАТЬ

ПланВидовХарактеристик.ХарактеристикиНоменклатуры.Ссылка КАК Характеристика,

УРОВЕНЬ(ПланВидовХарактеристик.ХарактеристикиНоменклатуры.Ссылка) КАК Уровень,

ПланВидовХарактеристик.ХарактеристикиНоменклатуры.Наименование КАК Наименование

ИЗ

ПланВидовХарактеристик.ХарактеристикиНоменклатуры КАК ПланВидовХарактеристик

ИЕРАРХИЯ ПО

ПланВидовХарактеристик.Ссылка

ИЕРАРХИЧЕСКИЙ ПРОХОД ВладелецПотомки

Ключевые отличия работы с ПВХ:

  • 🔑 Вместо РодительПотомки часто используется ВладелецПотомки.
  • 🔑 Уровни могут зависеть от вида характеристики, поэтому иногда требуется дополнительная фильтрация.
  • 🔑 В некоторых конфигурациях (например, ERP 2) ПВХ имеют сложную структуру с несколькими уровнями владельцев.

Если запрос к ПВХ возвращает неожиданные результаты, проверьте:

  1. Правильно ли указан владелец в параметре ИЕРАРХИЯ.
  2. Нет ли в конфигурации дополнительных обработчиков, модифицирующих иерархию (например, в модуле менеджера ПВХ).
  3. Не используются ли динамические списки, которые могут изменять структуру данных.
💡

При работе с ПВХ всегда проверяйте, какой тип иерархического прохода поддерживается в вашей конфигурации. В некоторых случаях может потребоваться обращение к виртуальной таблице ПланВидовХарактеристик.Имя.Иерархия.

Использование результатов в отчетах и формах

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

1. Вывод в табличный документ с отступами

Если вы формируете отчет в табличном документе, используйте значение уровня для создания отступов:

ТабличныйДокумент.ВывестиСтроку();

ТабличныйДокумент.УстановитьТекст(Повтор(" ", Уровень) + Наименование);

2. Настройка иерархии в СКД

В системе компоновки данных (СКД) для отображения иерархии:

  1. Добавьте поле Уровень в набор данных.
  2. В настройках группы укажите параметр Иерархия и выберите поле для группировки.
  3. Настройте отступы в параметрах оформления.

3. Динамический список с иерархией

Для отображения иерархического справочника в форме используйте реквизит типа ДеревоЗначений или ТаблицаЗначений с настройкой отступов:

Дерево = Новый ДеревоЗначений;

Дерево.Колонки.Добавить("Наименование");

Дерево.Колонки.Добавить("Уровень");

Для Каждого Строка Из РезультатЗапроса Цикл

Элемент = Дерево.Элементы.Добавить();

Элемент.Уровень = Строка.Уровень;

Элемент.Наименование = Повтор(" ", Строка.Уровень) + Строка.Наименование;

КонецЦикла;

Если иерархия не отображается корректно, проверьте:

  • 🖥️ Правильно ли заполнено свойство Уровень для каждого элемента ДеревоЗначений.
  • 🖥️ Нет ли в форме дополнительных фильтров, обрезающих дерево.
  • 🖥️ Соответствует ли порядок сортировки в запросе и в отображении.

FAQ: Частые вопросы по работе с уровнями в 1С

Можно ли получить уровень вложенности без использования функции УРОВЕНЬ()?

Технически да, но это не рекомендуется. Альтернативные способы:

  1. Рекурсивный обход справочника в цикле (очень медленно для больших данных).
  2. Хранение уровня в отдельном реквизите (требует поддержки при изменении иерархии).
  3. Использование виртуальных таблиц с предварительным расчетом уровней.

Функция УРОВЕНЬ() оптимизирована на уровне платформы и работает значительно быстрее.

Почему в некоторых конфигурациях уровни считаются неверно?

Это может быть связано с:

  • 🔧 Модифицированными обработчиками событий справочника (например, ПередЗаписью изменяет родителя).
  • 🔧 Особенностями конфигурации (например, в УТ 11 иерархия номенклатуры может зависеть от свойств).
  • 🔧 Ошибками в данных (циклические ссылки, когда элемент является родителем сам для себя).

Проверьте целостность данных с помощью обработки Тестирование и исправление.

Как вывести путь к элементу (цепочку родителей)?

Для этого используйте функцию ИЕРАРХИЯ() с параметром ИЕРАРХИЧЕСКИЙ ПРОХОД Родители:

ВЫБРАТЬ

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

ИЕРАРХИЯ(Справочник.Номенклатура.Ссылка) КАК Путь

ИЗ

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

ГДЕ

Справочник.Ссылка = &ТекущийЭлемент

ИЕРАРХИЯ ПО

Справочник.Ссылка

ИЕРАРХИЧЕСКИЙ ПРОХОД Родители

Результат в поле Путь будет содержать массив ссылок от корня до элемента.

Можно ли использовать УРОВЕНЬ() в запросах к регистрам сведений?

Нет, функция УРОВЕНЬ() работает только с иерархическими справочниками и планами видов характеристик. Для регистров сведений иерархия не поддерживается на уровне платформы.

Альтернатива: если в регистре хранятся данные с иерархической структурой (например, по подразделениям), сначала получите уровни справочника, а затем присоедините их к регистру.

Как ускорить запрос с иерархией для справочника с 50 000+ элементов?

Рекомендации для крупных справочников:

  • 🚀 Используйте УРОВЕНЬ ВЛОЖЕННОСТИ N для ограничения глубины.
  • 🚀 Замените рекурсивный обход на работу с виртуальной таблицей Справочник.Имя.Иерархия.
  • 🚀 Рассмотрите вариант денормализации: храните уровень в отдельном реквизите и обновляйте его при изменении иерархии.
  • 🚀 Разбейте запрос на части: сначала получите корневые элементы, затем дочерние (постранично).