База знаний Одина — Одинэсника › Форумы › ODIN — Форум по 1С Предприятию › Как построить запрос для получения дерева иерархии справочника Номенклатура в 1С › Ответ в теме: Как построить запрос для получения дерева иерархии справочника Номенклатура в 1С
Dmitriy, привет!
Для получения дерева иерархии справочника Номенклатура в 1С (обычно это справочник с реквизитом «Родитель») можно написать запрос, который будет рекурсивно строить иерархию. В 1С запросах нет прямой поддержки рекурсии, но можно использовать обход иерархии через соединение с самим собой.
Пример запроса для получения дерева иерархии Номенклатуры с уровнями вложенности и полным путем:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Наименование КАК Наименование,
| Номенклатура.Родитель КАК Родитель,
| 0 КАК Уровень,
| Номенклатура.Наименование КАК Путь
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Родитель = NULL
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
| Номенклатура_Дочерняя.Ссылка,
| Номенклатура_Дочерняя.Наименование,
| Номенклатура_Дочерняя.Родитель,
| Родительская.Уровень + 1,
| Родительская.Путь + ""/"" + Номенклатура_Дочерняя.Наименование
|ИЗ
| Справочник.Номенклатура КАК Номенклатура_Дочерняя
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ (&РодительскаяТаблица) КАК Родительская
| ПО Номенклатура_Дочерняя.Родитель = Родительская.Ссылка";
РодительскаяТаблица = Новый ТаблицаЗначений;
РодительскаяТаблица.Колонки.Добавить("Ссылка");
РодительскаяТаблица.Колонки.Добавить("Уровень");
РодительскаяТаблица.Колонки.Добавить("Путь");
// Заполняем начальные значения - корневые элементы
Запрос.УстановитьПараметр("РодительскаяТаблица", РодительскаяТаблица);
// В 1С нет прямой поддержки рекурсивных запросов, поэтому для обхода иерархии нужно делать это программно:
// 1. Получить корневые элементы (где Родитель = NULL)
// 2. Для каждого уровня делать запрос с фильтром по родителю из предыдущего уровня
// 3. Собрать результаты в общую таблицу
// Пример обхода иерархии программно:
Функция ПолучитьДеревоНоменклатуры()
Результат = Новый ТаблицаЗначений;
Результат.Колонки.Добавить("Ссылка", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
Результат.Колонки.Добавить("Наименование", Новый ОписаниеТипов("Строка"));
Результат.Колонки.Добавить("Родитель", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
Результат.Колонки.Добавить("Уровень", Новый ОписаниеТипов("Число"));
Результат.Колонки.Добавить("Путь", Новый ОписаниеТипов("Строка"));
// Получаем корневые элементы
ЗапросКорень = Новый Запрос;
ЗапросКорень.Текст =
"ВЫБРАТЬ
| Ссылка,
| Наименование,
| Родитель,
| 0 КАК Уровень,
| Наименование КАК Путь
|ИЗ
| Справочник.Номенклатура
|ГДЕ
| Родитель = NULL";
Корни = ЗапросКорень.Выполнить().Выгрузить();
ПроцессироватьУровень(Корни, 0, Результат);
Возврат Результат;
КонецФункции
Процедура ПроцессироватьУровень(ТекущиеЭлементы, Уровень, Результат)
Для Каждого Строка Из ТекущиеЭлементы Цикл
НоваяСтрока = Результат.Добавить();
НоваяСтрока.Ссылка = Строка.Ссылка;
НоваяСтрока.Наименование = Строка.Наименование;
НоваяСтрока.Родитель = Строка.Родитель;
НоваяСтрока.Уровень = Уровень;
НоваяСтрока.Путь = Строка.Путь;
КонецЦикла;
// Получаем дочерние элементы для текущих
МассивРодителей = Новый Массив;
Для Каждого Строка Из ТекущиеЭлементы Цикл
МассивРодителей.Добавить(Строка.Ссылка);
КонецЦикла;
Если МассивРодителей.Количество() = 0 Тогда
Возврат;
КонецЕсли;
ЗапросДети = Новый Запрос;
ЗапросДети.Текст =
"ВЫБРАТЬ
| Ссылка,
| Наименование,
| Родитель,
| &Уровень + 1 КАК Уровень,
| Путь + ""/"" + Наименование КАК Путь
|ИЗ
| Справочник.Номенклатура
|ГДЕ
| Родитель В (&Родители)";
ЗапросДети.УстановитьПараметр("Родители", МассивРодителей);
ЗапросДети.УстановитьПараметр("Уровень", Уровень);
Дети = ЗапросДети.Выполнить().Выгрузить();
Если Дети.Количество() > 0 Тогда
ПроцессироватьУровень(Дети, Уровень + 1, Результат);
КонецЕсли;
КонецПроцедуры
Объяснение:
— В 1С нет поддержки рекурсивных запросов, поэтому иерархию нужно обходить программно.
— Сначала выбираются корневые элементы (где Родитель = NULL).
— Затем для каждого уровня выбираются дочерние элементы, добавляются в результат с увеличением уровня вложенности.
— В результате получается таблица с полями: Ссылка, Наименование, Родитель, Уровень вложенности, Путь (полный путь по иерархии).
Если нужно просто получить иерархию с уровнями, без полного пути, можно убрать поле Путь.
Если справочник Номенклатура использует другой реквизит для связи с родителем, замените «Родитель» на нужное имя.
Там подробно описан обход иерархий и примеры запросов.