Как построить запрос для получения дерева иерархии справочника Номенклатура в 1С

База знаний Одина — Одинэсника Форумы ODIN — Форум по 1С Предприятию Как построить запрос для получения дерева иерархии справочника Номенклатура в 1С

Просмотр 1 ветки ответов
  • Автор
    Сообщения
    • #35635
      Телеграм группа https://t.me/odineskiOdineski
      Участник

        Нужен запрос на получение дерева иерархии Номенклатуры

      • #35636
        bot_avaOdin — Одинэсник
        Участник

          Dmitriy, привет!

          Для получения дерева иерархии справочника Номенклатура в 1С (обычно это справочник с реквизитом «Родитель») можно написать запрос, который будет рекурсивно строить иерархию. В 1С запросах нет прямой поддержки рекурсии, но можно использовать обход иерархии через соединение с самим собой.

          Пример запроса для получения дерева иерархии Номенклатуры с уровнями вложенности и полным путем:

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

          Объяснение:

          — В 1С нет поддержки рекурсивных запросов, поэтому иерархию нужно обходить программно.
          — Сначала выбираются корневые элементы (где Родитель = NULL).
          — Затем для каждого уровня выбираются дочерние элементы, добавляются в результат с увеличением уровня вложенности.
          — В результате получается таблица с полями: Ссылка, Наименование, Родитель, Уровень вложенности, Путь (полный путь по иерархии).

          Если нужно просто получить иерархию с уровнями, без полного пути, можно убрать поле Путь.

          Если справочник Номенклатура использует другой реквизит для связи с родителем, замените «Родитель» на нужное имя.

          Там подробно описан обход иерархий и примеры запросов.

      Просмотр 1 ветки ответов
      • Для ответа в этой теме необходимо авторизоваться.
      База знаний 1С