loading

ABAP CDS recursive association using hierarchy

Introduction

In this article, I will show a practical example of self-association in CDS. You will learn how to define a simple hierarchy in your CDS and how to consume it in your ABAP code.

The problem

Recently I have faced a quite interesting problem. There is a concept of something like ‘frame contract’. It means that out of this document many others of the same type (or not necessairely) can be created. Let’s take a look at VBFA table (Sales Document Flow). I am interested only in subsequent Sales Orders, therefore I have filtered out only documents of category ‘C’:

VBFA

What we can see is a ‘chain’ of documents, or even to be more specific – a tree. Let’s take a look at document 24. More friendly and eye-catching representation of the relationship between those documents would be:

hierarchy

Root parent of the above tree would be document 24 – our frame contract. Below it you will see it’s ‘children’ – subsequent documents. Now imagine that you would like to extract all documents related to your frame contract. Lot’s of twisted ABAP! Maybe there is an easier way of solving this riddle?

Gentle solutions

Yes! Fortunately, there is – we can avoid looping, reading, assigning and dumping.

CDS

We can define a CDS view which would have an association with itself. Let’s take a look:

CDS

I have defined a view Z_VBFA based on VBFA and added an association to Z_VBFA. As you can see preceding documents will be treated as parents and subsequent ones as children. The cardinality of the above association is [0..1] as there cannot be any multiple parents – one contract can only have one preceding document, however it can have multiple children. In order to allow consumption of such CDS annotation needs to be added:

hierarchy

It defines parent-child hierarchy and points at our self-association. There is also a second way of defining a hierarchy:

hierarchy2

I believe that the first one is much nicer. Remember that in that approach you should not use association.

Hierarchy

You can also define a hierarchy object Z_VBFA_HIERARCHY which would look like this:

VBFA Hierarchy

  • Source – Z_VBFA – previously defined view with self-association
  • Child to parent association – points at recursion association in the source
  • Siblings order – order of sibling nodes
  • Orphans root – orphans will be treated as roots. In our case contract 24 would be such node.
  • Multiple parents – this syntax is not used here as multiple parents are not allowed in my case

I have also listed out all $node fields. These are hierarchy-specific fields describing a hierarchy. We will take a look at them later. After running the hierarchy you will see a standard table view:

VBFA hierarchy 2

Gentle consumption

Now let’s take advantage of the work we have done here and let’s consume our objects in ABAP. There are few useful HIERARCHY functions – you can read more about them here https://help.sap.com/viewer/4fe29514fd584807ac9f2a04f6754767/2.0.01/en-US/fc59f81a5c494f399cc2ff70b9c3b4c9.html.

We will Focus on three of them:

  1. HIERARCHY – generates a hierarchy
  2. HIERARCHY_DESCENDANTS – Returns all descendants of a set of start nodes in a hierarchy. 
  3. HIERARCHY_ANCESTORS – Returns all ancestors of a set of start nodes in a hierarchy.

Let’s implement it in ABAP.

HIERARCHY

A hierarchy from CDS view with defined hierarchy will be generated. 

hierarchy from CDS

 

Selected fields are hierarchy nodes that are always available and describe the structure. You need to select them explicitly and add an alias. Let’s take a look at the SOURCE:

  • CHILD TO PARENT ASSOCIATION – points at recursive association in the view
  • START WHERE – points at a starting node in the hierarchy

 

Result:

INDEXPARENTNODELEVELRANKTREE_SIZE
110,0000000024;6,00000010,0000000025;6,0000001111
210,0000000025;6,00000010,0000000067;6,000000221
310,0000000025;6,00000010,0000000061;6,000000231
410,0000000025;6,00000010,0000000060;6,000000241
510,0000000025;6,00000010,0000000063;6,000000251
610,0000000025;6,00000010,0000000064;6,000000261
710,0000000025;6,00000010,0000000065;6,000000271
810,0000000025;6,00000010,0000000066;6,000000281
910,0000000025;6,00000010,0000000068;6,000000293
1010,0000000068;6,00000010,0000000069;6,0000003101
1110,0000000068;6,00000010,0000000070;6,0000003111

 

We get all relationships between nodes, starting from contract 24. What’s great all children are listed out in the node column, so our goal has been achieved. Let’s dig deeper into it however and take a look at hierarchy specific fields which may help us with traversing a hierarchy. Below pictures explain two of them:

Hierarchy level

hierarchy rank

HIERARCHY_DESCENDANTS

In this example however we are going to consume our CDS hierarchy directly.

Result:

INDEXPRECEDINGDOCUMENTPRECEDINGITEMSUBSEQUENTDOCUMENTSUBSEQUENTITEMPARENTNODECHILDNODEHIERARCHYISORPHANHIERARCHYLEVELHIERARCHYRANKHIERARCHYPARENTRANKHIERARCHYTREESIZE
1000000002400000000025010,0000000024;6,00000010,0000000025;6,000000112011
2000000002500000000067010,0000000025;6,00000010,0000000067;6,00000012321
3000000002500000000061010,0000000025;6,00000010,0000000061;6,00000012421
4000000002500000000060010,0000000025;6,00000010,0000000060;6,00000012521
5000000002500000000063010,0000000025;6,00000010,0000000063;6,00000012621
6000000002500000000064010,0000000025;6,00000010,0000000064;6,00000012721
7000000002500000000065010,0000000025;6,00000010,0000000065;6,00000012821
8000000002500000000066010,0000000025;6,00000010,0000000066;6,00000012921
9000000002500000000068010,0000000025;6,00000010,0000000068;6,000000121023
10000000006800000000069010,0000000068;6,00000010,0000000069;6,0000001311101
11000000006800000000070010,0000000068;6,00000010,0000000070;6,0000001312101

 

I used * sign in select, therefore, all fields from defined earlier CDS hierarchy were selected. Notice that in this case Z_VBFA_HIERARCHY is consumed, not Z_VBFA.

 

HIERARCHY_ANCESTORS

This function will return the ancestors of a given node.

Result:

INDEXPRECEDINGDOCUMENTPRECEDINGITEMSUBSEQUENTDOCUMENTSUBSEQUENTITEMPARENTNODECHILDNODEHIERARCHYISORPHANHIERARCHYLEVELHIERARCHYRANKHIERARCHYPARENTRANKHIERARCHYTREESIZE
1000000002400000000025010,0000000024;6,00000010,0000000025;6,000000112011

I have added orphans root annotation therefore one relationship in the hierarchy is displayed.

Alternative syntax

You can combine HIERARCHY and HIERARCHY_DESCENDANTS/HIERARCHY_ANCESTORS:

 

It will dynamically return hierarchy and apply HIERARCHY_DESCENDANTS on the result. Notice that we are not using Z_VBFA_HIERARCHY here but Z_VBFA. The result will be exactly the same as in HIERARCHY_DESCENDANTS.

Summary

I hope you can see the advantage of such solution. With few annotations and one select, we can extract the whole tree. With additional parameters like hierarchy_rank etc. it is incredibly easy to traverse through the whole structure. You can even select all other business data and have them all with one simple select. When possible avoid writing complex code!

 

ABAP developer and SAP integration consultant, SAP SDN contributor

Leave a Reply

Your email address will not be published. Required fields are marked *

Contact

INT4
ul. Bednarska 1
60-571 Poznan, Poland

 

office(at)int4.com

Write to us