Перейти до вмісту

Ієрархії в ABAP SQL

Ієрархічні дані — структури parent-child: організації, матеріали (BOM), дерева категорій. На HANA ABAP SQL має нативну підтримку: ієрархію описуєш один раз (CDS, HIERARCHY-генератор або CTE), далі ходиш по ній через навігатори HIERARCHY_DESCENDANTS, HIERARCHY_ANCESTORS, HIERARCHY_SIBLINGS та аґреґат-версії.

Раніше довелось би писати рекурсію або AMDP зі SQLScript. Зараз — декларативно, через стандартний ABAP SQL.

Три способи створити ієрархію

Section titled “Три способи створити ієрархію”

1. CDS hierarchy (рекомендовано для перевикористання)

Section titled “1. CDS hierarchy (рекомендовано для перевикористання)”

Визначається окремим обʼєктом DEFINE HIERARCHY, спираючись на CDS view з self-association. Найстійкіший варіант: логіка ієрархії винесена з програми, можна захистити через DCL.

// CDS view з self-асоціацією
define view entity zdemo_nodes
as select from zdemo_abap_hnodes
association [0..1] to zdemo_nodes as _parent
on $projection.parent_id = _parent.id
{
key id,
parent_id,
name,
_parent
}
// Hierarchy
define hierarchy zdemo_node_hier
with parameters p_root : abap.numc(4)
as parent child hierarchy(
source zdemo_nodes
child to parent association _parent
start where id = :p_root
siblings order by name
)
{ id, parent_id, name }

Той самий синтаксис, але inline у ABAP SQL. Зручно для одноразового використання:

SELECT * FROM HIERARCHY(
SOURCE zdemo_nodes
CHILD TO PARENT ASSOCIATION _parent
START WHERE id = @root
SIBLINGS ORDER BY name )
INTO TABLE @DATA(tree).

3. CTE як джерело ієрархії

Section titled “3. CTE як джерело ієрархії”

CTE оголошується ієрархією через додаток WITH HIERARCHY <name> (посилається на існуючий CDS hierarchy). Після цього з CTE можна читати неявні hierarchy-колонки:

WITH
+tree AS ( SELECT FROM zdemo_node_hier( p_root = @root )
FIELDS * )
WITH HIERARCHY zdemo_node_hier
SELECT FROM +tree
FIELDS id, name, hierarchy_level, hierarchy_rank
INTO TABLE @DATA(out).

Також можна використати HIERARCHY( ... ) як джерело всередині CTE — як у прикладі вище з inline-генератором.

Доступні автоматично при виборці з ієрархії:

КолонкаЗначення
hierarchy_rankПорядковий номер у обході (preorder)
hierarchy_tree_sizeКількість нащадків + 1 (розмір піддерева)
hierarchy_parent_rankRank батька
hierarchy_levelГлибина (root = 1)
hierarchy_is_cycleПрапорець: вузол у циклі
hierarchy_is_orphanПрапорець: сирота (батько не знайдений)

Повертає усіх нащадків заданих стартових вузлів. Додає колонку HIERARCHY_DISTANCE (≥ 0 — скільки рівнів донизу).

SELECT * FROM HIERARCHY_DESCENDANTS(
SOURCE zdemo_node_hier( p_root = '0001' )
START WHERE id = @start_node
DISTANCE FROM 1 TO 3 ) " опціонально обмежити діапазон глибини
INTO TABLE @DATA(desc).

Параметр DISTANCE обмежує, на скільки рівнів донизу йти від стартового вузла. Без нього — без обмежень.

Те саме, але вгору: повертає предків від стартового вузла до кореня. Колонка HIERARCHY_DISTANCE показує, скільки рівнів догори від стартового вузла (≥ 0).

SELECT * FROM HIERARCHY_ANCESTORS(
SOURCE zdemo_node_hier( p_root = '0001' )
START WHERE id = @leaf )
INTO TABLE @DATA(anc).

Вузли з тим самим батьком. Додає HIERARCHY_SIBLING_DISTANCE.

SELECT * FROM HIERARCHY_SIBLINGS(
SOURCE zdemo_node_hier( p_root = '0001' )
START WHERE id = @node )
INTO TABLE @DATA(sib).

HIERARCHY_DESCENDANTS_AGGREGATE і HIERARCHY_ANCESTORS_AGGREGATE — аґреґують значення по піддереву/по шляху до кореня.

" Сума amount по піддереву кожного вузла
SELECT * FROM HIERARCHY_DESCENDANTS_AGGREGATE(
SOURCE zdemo_node_hier( p_root = '0001' ) AS h
JOIN @values AS v ON v~id = h~id
MEASURES SUM( v~amount ) AS total
WHERE hierarchy_rank > 1
WITH SUBTOTAL
WITH BALANCE )
INTO TABLE @DATA(totals).
  • MEASURES — які аґреґати обчислити (SUM, MIN, MAX, AVG, COUNT).
  • WHERE (після MEASURES) — відбирає вузли, для яких обчислюється SUBTOTAL.
  • WITH SUBTOTAL — додає рядки-підсумки для вузлів, що збігаються з WHERE.
  • WITH BALANCE — додає рядки-різниці для решти вузлів.

Колонка HIERARCHY_AGGREGATE_TYPE: 1 — subtotal, 2 — balance.

Типові задачі → який навігатор

Section titled “Типові задачі → який навігатор”
ЗадачаІнструмент
Показати дерево від кореняHIERARCHY() або CDS hierarchy
”Усі підрозділи під цим департаментом”HIERARCHY_DESCENDANTS
”Шлях від листа до кореня”HIERARCHY_ANCESTORS
”Сусідні категорії”HIERARCHY_SIBLINGS
”Сума витрат по піддереву”HIERARCHY_DESCENDANTS_AGGREGATE
”Накопичена сума вгору по дереву”HIERARCHY_ANCESTORS_AGGREGATE

Адаптовано з 10_ABAP_SQL_Hierarchies.md (Apache 2.0). Повний перелік нюансів — в оригіналі.