Структура иерархического справочника запросом

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

Допустим имеем иерархический справочник «Подразделения» с неизвестным (неограниченным) уровнем вложенности:

Подр1

Подр11

Подр12

Подр121

Подр122

Подр13

ПодрN

И требуется получить таблицу следующей структуры:

Подразделение Уровень
0
Уровень
1
Уровень
2
Уровень
Макс-1
Уровень
Макс
Подр1 Подр1          
Подр11 Подр1 Подр11        
Подр12 Подр1 Подр12        
Подр121 Подр1 Подр12 Подр121      
Подр122 Подр1 Подр12 Подр122      
           
ПодрN ПодрN          

 

Пример:

Пример

 

Предлагаю следующий вариант решения:

// Определим максимальный уровень иерархии справочника
Запрос = Новый Запрос;
Запрос.Текст =
    «ВЫБРАТЬ
    |   Подразделения.Ссылка
    |ИЗ
    |   Справочник.Подразделения КАК Подразделения»;
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
МаксУровень = 0;
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
    МаксУровень = Макс(ВыборкаДетальныеЗаписи.Ссылка.Уровень(), МаксУровень);
КонецЦикла;

// Соберем текст запроса для получения следующей структуры полей выборки:
//      Подразделение, Уровень0, Уровень1, …, УровеньN-1, УровеньN.
// где N — максимальный уровень иерархии.

// Начало текста запроса
Запрос.Текст =
    «ВЫБРАТЬ
    |   *
    |ИЗ
    |   («;
// Нулевой уровень иерархии
ТекущийУровень = 0;
Запрос.Текст = Запрос.Текст + «
    |ВЫБРАТЬ
    |   Подразделения.Ссылка КАК Подразделение
    |   , Подразделения.Ссылка КАК Уровень0″;
Для Сч=1 По МаксУровень Цикл
    Запрос.Текст = Запрос.Текст + «
        |   , ЗНАЧЕНИЕ(Справочник.Подразделения.ПустаяСсылка) КАК Уровень»+Сч;
КонецЦикла;
Запрос.Текст = Запрос.Текст + «
    |ИЗ
    |   Справочник.Подразделения КАК Подразделения
    |ГДЕ
    |   Подразделения.Родитель = ЗНАЧЕНИЕ(Справочник.Подразделения.ПустаяСсылка)»;
// Последующие уровни иерархии.
Для ТекущийУровень = 1 По МаксУровень Цикл
    Запрос.Текст = Запрос.Текст + «
        |
        |ОБЪЕДИНИТЬ ВСЕ
        |
        |ВЫБРАТЬ
        |   Подразделения.Ссылка КАК Подразделение»;
    Для Сч1=0 По ТекущийУровень1 Цикл
        Запрос.Текст = Запрос.Текст + «
        |   , Подразделения»;
        Для Сч2=1 по ТекущийУровеньСч1 Цикл
            Запрос.Текст = Запрос.Текст + «.Родитель»;
        КонецЦикла;
        Запрос.Текст = Запрос.Текст + » КАК Уровень»+Сч1;
    КонецЦикла;
    Запрос.Текст = Запрос.Текст + «
        |   , Подразделения.Ссылка КАК Уровень»+ТекущийУровень;
    Для Сч=ТекущийУровень+1 По МаксУровень Цикл
        Запрос.Текст = Запрос.Текст + «
            |   , ЗНАЧЕНИЕ(Справочник.Подразделения.ПустаяСсылка) КАК Уровень»+Сч;
    КонецЦикла;
    Запрос.Текст = Запрос.Текст + «
        |ИЗ
        |   Справочник.Подразделения КАК Подразделения
        |ГДЕ
        |   Подразделения.Родитель»;
    Для Сч2=1 по ТекущийУровень Цикл
        Запрос.Текст = Запрос.Текст + «.Родитель»;
    КонецЦикла;
    Запрос.Текст = Запрос.Текст + » = ЗНАЧЕНИЕ(Справочник.Подразделения.ПустаяСсылка)»;
КонецЦикла;
// Финиш текста запроса
Запрос.Текст = Запрос.Текст + «
    |   ) КАК Структура
    |УПОРЯДОЧИТЬ ПО
    |   Структура.Уровень0.Наименование»;
Для Сч=1 По МаксУровень Цикл
    Запрос.Текст = Запрос.Текст + «
        |   , Структура.Уровень»+Сч+«.Наименование»;
КонецЦикла;

Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();

Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
    // Обход выборки.
КонецЦикла;

 

У данного решения есть минусы, которые я пока не смог обойти:

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

2. При большом максимальном уровне вложенности может быть будут проблемы с запросом (в местах, где множится «…Родитель.Родитель.Родитель…»). Я тестировал на 20 уровне вложенности.

2 Comments

  1. AlexProg

    (1) Eugeneer, чья бы корова мычала, твоя бы молчала.

    Reply
  2. ildarovich

    В статье Уровни, глубина, прародители, циклы и аналоги запросом показано, как одним запросом быстро получить в том числе и максимальный уровень справочника.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *