Работа с иерархическими справочниками — ежедневная задача разработчика 1С․ Платформа предоставляет мощный инструментарий для отбора, упорядочивания и группировки данных с учетом иерархии․ В этой статье подробно разберем, как проверить вхождение элемента в иерархию, как выбирать целые ветви дерева, как правильно строить отчеты с группировкой по иерархии и какие подводные камни существуют при этом․
Оператор В ИЕРАРХИИ — основной инструмент отбора
Ключевым словом для проверки принадлежности элемента иерархии является оператор В ИЕРАРХИИ․ Он используется в секции ГДЕ запроса и позволяет отобрать не только сам элемент-группу, но и все его подчиненные элементы (вглубь по дереву) на любом уровне вложенности․
Синтаксис
ГДЕ Справочник․Поле В ИЕРАРХИИ (&ПараметрРодитель) Пример: Выборка всей номенклатуры определенной группы
Допустим, нам нужны все товары, входящие в группу «Бытовая техника» и её подгруппы․
ВЫБРАТЬ
Номенклатура․Ссылка,
Номенклатура․Наименование,
Номенклатура․Родитель
ИЗ
Справочник․Номенклатура КАК Номенклатура
ГДЕ
Номенклатура․Родитель В ИЕРАРХИИ (&ГруппаБытоваяТехника)
УПОРЯДОЧИТЬ ПО
Наименование ИЕРАРХИЯ Важные нюансы:
- Оператор работает по полю Родитель (или иному полю иерархии, если справочник имеет несколько иерархий)․
- В параметр можно передать как единичную ссылку (
СправочникСсылка․Номенклатура), так и массив ссылок илиСписокЗначений(на новых платформах лучше использовать Массив, так как со списком значений может браться только первое значение)․ - Проверка идет по полному пути: элемент считается входящим в иерархию, если его родитель (или родитель родителя и т․д․) равен переданному параметру․
Обратная проверка: Является ли элемент родителем для заданного?
Часто возникает задача: «Является ли текущий элемент (группа) родителем для конкретного элемента (элемента)?»․ Стандартный В ИЕРАРХИИ работает «сверху вниз» (Родитель -> Потомки)․ Для обратной проверки («снизу вверх») есть два подхода․
Способ 1: Через ВЫБОР (для единичной проверки)
Пример с форума Infostart (2020):
ВЫБОР
КОГДА ВЫРАЗИТЬ(&Склад КАК Справочник․Склады) В ИЕРАРХИИ (&ОбъектСкладРодитель)
ТОГДА ИСТИНА
ИНАЧЕ ЛОЖЬ
КОНЕЦ Здесь мы проверяем, входит ли конкретный &Склад в иерархию &ОбъектСкладРодитель․
Способ 2: Транзитивное замыкание (для массовой проверки)
Если нужно найти все родительские группы для набора элементов, эффективнее использовать запрос с транзитивным замыканием (рекурсивным CTE или временными таблицами), так как в 1С нет нативных рекурсивных запросов (CTE WITH RECURSIVE не поддерживается)․
Упорядочивание результатов по иерархии (УПОРЯДОЧИТЬ ПО ․․․ ИЕРАРХИЯ)
Для визуального представления дерева в отчете или при обходе выборки в коде используется конструкция УПОРЯДОЧИТЬ ПО <Поле> ИЕРАРХИЯ․
Пример
ВЫБРАТЬ
Подразделения․Наименование
ИЗ
Справочник․Подразделения КАК Подразделения
УПОРЯДОЧИТЬ ПО
Наименование ИЕРАРХИЯ Результат будет отсортирован так, чтобы группы шли перед своими элементами, сохраняя структуру дерева․ Это критически важно для алгоритмов обхода выборки (Выборка․Следующий с вложенными циклами по Выборка․Выбрать)․
Согласно разбору тестирования «1С:Профессионал» и PMP, для получения итогов по иерархии (чтобы строка группы содержала сумму по себе и всем подгруппам) необходимо в настройках схемы компоновки или в тексте запроса указать правильный Тип итогов для группировочного поля․
Правильные варианты (Типы итогов):
- Элементы и иерархия — выводит строки и для групп (с итогами по поддереву), и для элементов․
- Только иерархия — выводит строки только для групп (итоги по поддереву), элементы в строки не попадают (но учитываются в итогах групп)․
Неправильно: Тип итогов «Элементы» — не даст итогов по группам․
Продвинутые техники: Получение дерева и уровней вложенности
Поскольку в 1С нет рекурсивных SQL-запросов, для построения полного дерева с уровнями вложенности (Level) и полным путем (Path) используют три основных подхода (по материалам блога Кухара Богдана и методических рекомендаций 1С):
Способ 1: Запрос с итогами по иерархии (Самый простой для отчетов)
Используется в СКД․ Платформа сама строит дерево на основе поля Родитель и типа итогов․
Способ 2: Обход выборки, упорядоченной по иерархии (Программный)
- Выполняем запрос с
УПОРЯДОЧИТЬ ПО Родитель ИЕРАРХИЯ․ - Обходим выборку рекурсивной функцией или стеком, анализируя смену уровней вложенности (сравнивая Родитель текущей строки с Родителем предыдущей)․
Способ 3: Транзитивное замыкание через временные таблицы (Для сложной аналитики)
Алгоритм:
- Помещаем в ВТ все пары «Потомок, Прямой Родитель»․
- В цикле (пока добавляются строки) присоединяем ВТ к самой себе: «Потомок — Родитель Родителя»․
- Получаем полную матрицу связей «Каждый элемент — Все его предки»․
Это позволяет мгновенно отвечать на вопросы: «Все родители элемента», «Все дети группы», «Уровень вложенности»․
Типичные ошибки и лучшие практики
| Ошибка / Проблема | Решение / Лучшая практика |
|---|---|
| Передача в В ИЕРАРХИИ СпискаЗначений | На платформе 8․3․17+ в В ИЕРАРХИИ из СпискаЗначений берется только первое значение․ Всегда преобразуйте в Массив (СписокЗначений․ВыгрузитьКолонку("Значение"))․ |
| Проверка вхождения в иерархию для Неопределенного (пустой ссылки) | Пустая ссылка не входит ни в какую иерархию․ Добавьте проверку: ГДЕ Номенклатура․Родитель В ИЕРАРХИИ (&Группа) ИЛИ Номенклатура․Родитель = &Группа (если нужно вклють саму группу) или обрабатывайте пустые ссылки отдельно․ |
| Медленная работа В ИЕРАРХИИ на больших таблицах | Убедитесь, что по полю Родитель построен индекс (по умолчанию есть)․ Не используйте В ИЕРАРХИИ в связке с ОР для огромных списков параметров — лучше загрузить параметры во ВременнуюТаблицу и сделать СОЕДИНЕНИЕ․ |
| Потеря иерархии при УПОРЯДОЧИТЬ ПО Наименование | УПОРЯДОЧИТЬ ПО Наименование ИЕРАРХИЯ сортирует внутри уровней по имени․ Если нужно строгое дерево, сортируйте по Родитель ИЕРАРХИЯ или используйте предварительную нумерацию (Preorder traversal)․ |
| Попытка использовать рекурсивный CTE (WITH RECURSIVE) | Не поддерживается языком запросов 1С․ Используйте временные таблицы и циклы в коде или пакетные запросы․ |
Пример универсальной функции: ПолучитьВсехПотомков(Родитель)
Часто используется паттерн: выбрать в ВременнуюТаблицу все конечные элементы (или все элементы) по заданному корню․
// Параметр: Родитель ⸺ СправочникСсылка
// Возвращает: ТаблицаЗначений (Ссылка, Уровень, Родитель)
Запрос = Новый Запрос;
Запрос․Текст =
"ВЫБРАТЬ
| Номенклатура․Ссылка КАК Ссылка,
| Номенклатура․Родитель КАК Родитель,
| 0 КАК Уровень
|ПОМЕСТИТЬ ВТ_База
|ИЗ
| Справочник․Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура․Родитель В ИЕРАРХИИ (&Родитель)
| ИЛИ Номенклатура․Ссылка = &Родитель
|;";
// Если нужно только конечные элементы (не группы), добавляем:
// | И Номенклатура․ЭтоГруппа = ЛОЖЬ
Запрос․УстановитьПараметр("Родитель", Родитель);
Результат = Запрос․Выполнить;
Возврат Результат․Выгрузить; Работа со старыми платформами (8․2․14 и ниже)
На очень старых платформах (до 8․2․16-8․3․0) поведение В ИЕРАРХИИ с параметрами-массивами могло отличаться․ Универсальный «старый» способ — загрузка списка групп во временную таблицу и соединение:
ВЫБРАТЬ
Номенклатура․Ссылка
ИЗ
Справочник․Номенклатура КАК Номенклатура
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Группы КАК Группы
ПО Номенклатура․Родитель = Группы․Ссылка Где ВТ_Группы заполнена рекурсивно всеми подгруппами корневой группы․
Проверка в иерархии в 1С строится вокруг оператора В ИЕРАРХИИ и конструкции УПОРЯДОЧИТЬ ПО ․․․ ИЕРАРХИЯ․ Главные правила успешной работы:
- Используйте Массив для передачи множества родителей в параметр
В ИЕРАРХИИ․ - Для отчетов с итогами настраивайте Тип итогов: «Элементы и иерархия» или «Только иерархия»․
- Для программного обхода дерева всегда применяйте
УПОРЯДОЧИТЬ ПО Родитель ИЕРАРХИЯ․ - Для сложных задач (пути, уровни, все предки) используйте алгоритм транзитивного замыкания через временные таблицы․
Понимание этих механизмов позволяет писать эффективные, быстрые и правильные запросы к иерархическим данным любой сложности․