Допустим имеем иерархический справочник «Подразделения» с неизвестным (неограниченным) уровнем вложенности:
Подр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 уровне вложенности.
(1) Eugeneer, чья бы корова мычала, твоя бы молчала.
В статьеУровни, глубина, прародители, циклы и аналоги запросом показано, как одним запросом быстро получить в том числе и максимальный уровень справочника.