При разработке отчетов и обработок в 1С часто возникает задача: выбрать элементы справочника (например, Номенклатура) и определить, к какой именно из заданных верховых групп (родителей) они принадлежат. Если иерархия имеет развитую структуру со множеством подгрупп (Товары11, Товары12, Товары131 и т. д.), простым обращением к реквизиту Родитель обойтись не удастся.
Рассмотрим, с какими ограничениями платформы 1С можно столкнуться при решении этой задачи и как правильно построить запрос для получения оптимального результата.
Проанализируем базовые ограничения языка запросов 1С, которые мешают решить задачу «в лоб»:
В ИЕРАРХИИ в секции группировки: Платформа не позволяет группировать данные по выражению, содержащему иерархическую проверку. Попытка написать ГРУППИРОВАТЬ ПО ВЫБОР КОГДА Номенклатура В ИЕРАРХИИ(&Группа1) ... приведет к ошибке выполнения запроса.В ИЕРАРХИИ нельзя использовать в секции ПО при левом, правом или полном соединении таблиц.Разберем наиболее изящные и производительные способы обхода этих ограничений.
Чтобы обойти запрет на группировку по иерархическому выражению, разделим выполнение на два шага в рамках одного пакетного запроса.
Шаг 1. В первом запросе вычисляем родительскую группу с помощью конструкции ВЫБОР КОГДА ... В ИЕРАРХИИ и сохраняем результат во временную таблицу.
Шаг 2. Во втором запросе обращаемся к временной таблице, где поле с родительской группой уже является готовой ссылкой, и свободно выполняем любые группировки или агрегации.
Рассмотрим пример кода 1С:
ВЫБРАТЬ
Товары.Ссылка КАК Товар,
ВЫБОР
КОГДА Товары.Ссылка В ИЕРАРХИИ(&ГруппаТовары1) ТОГДА &ГруппаТовары1
КОГДА Товары.Ссылка В ИЕРАРХИИ(&ГруппаТовары2) ТОГДА &ГруппаТовары2
КОГДА Товары.Ссылка В ИЕРАРХИИ(&ГруппаТовары3) ТОГДА &ГруппаТовары3
КОНЕЦ КАК РодительскаяГруппа
ПОМЕСТИТЬ ВТ_ТоварыСГруппами
ИЗ
Справочник.Номенклатура КАК Товары
ГДЕ
Товары.Ссылка В ИЕРАРХИИ(&СписокВсехГрупп);
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВТ.РодительскаяГруппа КАК РодительскаяГруппа,
ВТ.Товар КАК Товар,
КОЛИЧЕСТВО(1) КАК Количество
ИЗ
ВТ_ТоварыСГруппами КАК ВТ
ГРУППИРОВАТЬ ПО
ВТ.РодительскаяГруппа,
ВТ.Товар;
Этот подход не требует динамического формирования текста запроса в цикле через ОБЪЕДИНИТЬ ВСЕ, выглядит лаконично и выполняется достаточно быстро на стороне СУБД.
Если глубина вложенности справочника заранее ограничена (например, структура гарантированно не превышает 3–4 уровней), можно обойтись без оператора В ИЕРАРХИИ. В этом случае проверка выполняется через последовательное обращение к родительским элементам.
Посмотрим на пример такого запроса:
ВЫБРАТЬ
Товары.Ссылка КАК Товар,
ВЫБОР
КОГДА Товары.Родитель В (&СписокРодительскихГрупп)
ТОГДА Товары.Родитель
КОГДА Товары.Родитель.Родитель В (&СписокРодительскихГрупп)
ТОГДА Товары.Родитель.Родитель
КОГДА Товары.Родитель.Родитель.Родитель В (&СписокРодительскихГрупп)
ТОГДА Товары.Родитель.Родитель.Родитель
КОНЕЦ КАК РодительскаяГруппа
ИЗ
Справочник.Номенклатура КАК Товары
ГДЕ
Товары.Ссылка В ИЕРАРХИИ(&СписокРодительскихГрупп);
Преимущества метода:
Родитель, что обеспечивает высокую скорость выполнения.Недостаток: метод не сработает для элементов, расположенных глубже, чем количество прописанных уровней Родитель.Родитель....
Если задача решается в рамках разработки отчета, оптимальным выбором будет применение СКД. Система компоновки данных умеет самостоятельно обрабатывать иерархические связи наборов данных.
Проанализируем порядок действий при работе с СКД:
Ссылка с полем Родитель (указывается начальное значение и выражение связи).Это позволяет полностью переложить распределение элементов по группам на платформу 1С без усложнения текста запроса.