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

Программист 1С v8.3 (Управляемые формы)
← К списку

При работе с иерархическими справочниками в 1С часто возникает необходимость получить информацию о родительских элементах. Это может быть как непосредственный родитель, так и самый верхний элемент в иерархии, так называемый "прародитель". Кроме того, для анализа данных по таким справочникам мы можем использовать мощный механизм итогов по иерархии. В этом руководстве мы подробно разберем, как решать эти задачи, опираясь на опыт разработчиков 1С.

Давайте вместе проанализируем различные подходы и выясним, какой из них наилучшим образом подходит для вашей конкретной ситуации.

Получение непосредственного родителя элемента

Начнем с самой простой и очевидной задачи: получения кода непосредственного родителя элемента справочника. В платформе 1С иерархические справочники имеют встроенный реквизит Родитель, который хранит ссылку на вышестоящий элемент.

  1. Использование реквизита Родитель:
  2. Мы можем напрямую обратиться к этому реквизиту через точку, чтобы получить ссылку на родителя. Если нам нужен его код, мы можем обратиться к свойству Код родителя.

  3. Пример запроса:
  4. Рассмотрим пример запроса, который получает ссылку на элемент справочника "ДоговорыКонтрагентов" и код его непосредственного родителя:

    
    Запрос.Текст =
    "ВЫБРАТЬ
        ДоговорыКонтрагентов.Ссылка,
        ДоговорыКонтрагентов.Родитель.Код КАК РодительКод
    ИЗ
        Справочник.ДоговорыКонтрагентов КАК ДоговорыКонтрагентов
    СГРУППИРОВАТЬ ПО
        ДоговорыКонтрагентов.Родитель.Код,
        ДоговорыКонтрагентов.Ссылка
    ИТОГИ ПО
        РодительКод";
    РезультатЗапроса = Запрос.Выполнить();
    

    В этом запросе мы обращаемся к ДоговорыКонтрагентов.Родитель.Код, чтобы получить код родителя для каждого элемента. Конструкция ИТОГИ ПО РодительКод позволяет нам получить агрегированные данные по каждому уникальному коду родителя, если это требуется. Однако для простой выборки непосредственного родителя, часть с СГРУППИРОВАТЬ ПО и ИТОГИ ПО может быть упрощена, если нам не нужны агрегации.

Получение самого верхнего родителя (прародителя) в иерархии

Задача получения кода самого верхнего родителя в иерархии является более сложной, поскольку глубина вложенности может быть неизвестна заранее. Давайте рассмотрим несколько подходов к ее решению.

  1. Многократное обращение к реквизиту Родитель:
  2. Если количество уровней иерархии фиксировано и известно заранее, мы могли бы обращаться к свойству Родитель несколько раз: СправочникСсылка.Родитель.Родитель.Родитель. Однако этот метод не является универсальным и не подходит для произвольной глубины вложенности.

  3. Использование функций на встроенном языке (рекурсия):
  4. Мы можем написать функцию на встроенном языке 1С, которая будет рекурсивно подниматься по иерархии, пока не встретит элемент, у которого реквизит Родитель пуст. Это и будет наш верхний родитель.

    
    Функция ПолучитьВерхнегоРодителя(ЭлементСправочника)
        ТекущийЭлемент = ЭлементСправочника;
        Пока ЗначениеЗаполнено(ТекущийЭлемент.Родитель) Цикл
            ТекущийЭлемент = ТекущийЭлемент.Родитель;
        КонецЦикла;
        Возврат ТекущийЭлемент;
    КонецФункции
    

    Этот метод работает, но может быть неоптимален для больших объемов данных, так как выполняется на стороне клиента или сервера 1С и требует множественных обращений к базе данных.

  5. Транзитивное замыкание в запросах:
  6. Для универсального и производительного получения всех предков или потомков в иерархическом справочнике мы можем использовать механизм транзитивного замыкания в запросах 1С. Это мощный инструмент, который позволяет найти всю цепочку родителей до самого верхнего уровня одним пакетным запросом. Транзитивное замыкание особенно полезно для сложных аналитических задач.

    Для реализации транзитивного замыкания часто используются временные таблицы и пакетные запросы. Существуют готовые функции, генерирующие такие запросы, которые учитывают все уровни вложенности.

  7. Добавление служебного реквизита:
  8. Как альтернативное решение, мы можем добавить служебный реквизит, например, РодительВерхнегоУровня, непосредственно в справочник. Этот реквизит будет заполняться при записи элемента и содержать ссылку на самый верхний элемент иерархии. Этот подход требует дополнительных доработок конфигурации и поддержания актуальности данных, но обеспечивает быстрый доступ к информации о верхнем родителе без сложных запросов.

Использование ИТОГИ ПО ... ИЕРАРХИЯ для агрегации данных

Теперь давайте рассмотрим, как работать с иерархическими итогами в запросах 1С. Конструкция ИТОГИ ПО <Поле> ИЕРАРХИЯ позволяет получить агрегированные данные по каждому уровню иерархии справочника. Это очень удобно, когда нам нужно подвести итоги не только по отдельным элементам, но и по их группам.

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

    
    ВЫБРАТЬ
      ТаблицаЗначенийСписок.ЭтапРабота КАК ЭтапРабота,
      ТаблицаЗначенийСписок.КодСДР КАК КодСДР,
      ТаблицаЗначенийСписок.НачалоРабот КАК НачалоРабот,
      ТаблицаЗначенийСписок.ОкончаниеРабот КАК ОкончаниеРабот
    ПОМЕСТИТЬ ВТ_Список
    ИЗ
      &ТаблицаЗначенийСписок КАК ТаблицаЗначенийСписок
    ;
    
    ////////////////////////////////////////////////////////////////////////////////
    ВЫБРАТЬ
      ВидыРабот.Ссылка КАК ЭтапРабота,
      ВидыРабот.Код КАК КодСДР,
      ВТ_Список.НачалоРабот КАК НачалоРабот,
      ВТ_Список.ОкончаниеРабот КАК ОкончаниеРабот
    ИЗ
      ВТ_Список КАК ВТ_Список
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.ВидыРабот КАК ВидыРабот
        ПО (ВТ_Список.ЭтапРабота = ВидыРабот.Ссылка)
    ИТОГИ
      КодСДР КАК КодСДР,
      МИНИМУМ(НачалоРабот),
      МАКСИМУМ(ОкончаниеРабот)
    ПО
      ЭтапРабота ИЕРАРХИЯ
    
  3. Разберем этот запрос по шагам:
  4. Преимущества ИТОГИ ПО ... ИЕРАРХИЯ:
  5. Эта конструкция позволяет нам получать не просто плоский список данных, а структурированный результат, в котором мы видим агрегированные значения для каждого элемента и для каждой группы в иерархии. Это незаменимо для построения отчетов с детализацией по группам и общими итогами.

  6. Упорядочивание иерархических данных:
  7. Для корректного отображения иерархии в отчете мы также можем использовать конструкцию УПОРЯДОЧИТЬ ПО <Поле> ИЕРАРХИЯ. Например, УПОРЯДОЧИТЬ ПО Номенклатура.ЭтоГруппа ИЕРАРХИЯ, Наименование позволит нам правильно отсортировать элементы, размещая группы выше подчиненных элементов.

Дополнительные полезные методы для работы с иерархией

Помимо рассмотренных выше методов, существуют и другие, которые могут быть полезны при работе с иерархическими справочниками:

  1. Оператор В ИЕРАРХИИ:
  2. Для получения всех подчиненных элементов и групп заданной группы (включая саму группу) в запросах мы можем использовать оператор В ИЕРАРХИИ. Например: ГДЕ Номенклатура.Ссылка В ИЕРАРХИИ(&Группа).

  3. Свойство РодительВерхнегоУровня:
  4. Для табличных полей, отображающих данные в виде дерева или иерархического списка на форме, существует свойство РодительВерхнегоУровня. Оно позволяет установить, с какого уровня иерархии начинать отображение данных, включая все подчиненные уровни. Если значение свойства Неопределено, отображается весь список; иначе — только строки, подчиненные указанной строке. Это полезно для ограничения выбора элементов.

Мы рассмотрели основные подходы к получению кода родителя в иерархических справочниках 1С, включая самый верхний уровень, а также изучили мощные возможности иерархических итогов в запросах. Выбирайте метод, который наилучшим образом соответствует вашим требованиям к производительности и гибкости решения.

← К списку