do you know a efficient method to generate a parent-child hierarchy from a table without parent node IDs. The parent child relationship should be switchable. All of this should be done in ABAP.
example data:
Color producer weight Airplane(key)
green CompanyA 330 A350
green CompanyA 222 A320
green CompanyB 222 B450
yellow CompanyA 330 H450
I want generate a child parent relationship based on this rows: producer weight Airplane and ignore color. Then i will change it and use: Color weight Airplane and ignore producer
At the end i need a result looks like for "producer weight Airplane"
CompanyA CompanyB
330 222 222
A350 A320 B450
H450
in a internal table it should look like this at the end
ID attribute value H_level parentID
1 producer CompanyA 1
2 weight 330 2 1
3 airplane A350 3 2
.....
does anyone have a good efficient idea? Thanks a lot.
Here is a simple tree-building algorithm that does what you need.
Note that this algorithm is not optimized in terms of performance. If you manage large amounts of data, you may want to revise some aspects, for example use SORTED or HASHED rather than STANDARD tables to improve the lookup READ TABLEs.
The algorithm is also not refactored for optimum code style. For example, clean code suggests we may want to extract a couple of methods to improve readability.
CLASS hierarchy_builder DEFINITION
PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES:
BEGIN OF ts_input,
color TYPE string,
producer TYPE string,
weight TYPE string,
airplane TYPE string,
END OF ts_input.
TYPES tt_input TYPE
STANDARD TABLE OF ts_input
WITH EMPTY KEY.
TYPES tt_attributes TYPE string_table.
TYPES:
BEGIN OF ts_output,
id TYPE string,
attribute TYPE string,
value TYPE string,
level TYPE i,
parent_id TYPE string,
END OF ts_output.
TYPES tt_output
TYPE STANDARD TABLE OF ts_output
WITH EMPTY KEY.
CLASS-METHODS build_hierarchy
IMPORTING
it_data TYPE tt_input
it_hierarchy TYPE tt_attributes
RETURNING
VALUE(rt_result) TYPE tt_output.
ENDCLASS.
CLASS hierarchy_builder IMPLEMENTATION.
METHOD build_hierarchy.
DATA(lv_parent_attribute) = ``.
DATA(lv_next_id) = 1.
LOOP AT it_hierarchy INTO DATA(lv_child_attribute).
DATA(lv_level) = sy-tabix.
LOOP AT it_data INTO DATA(ls_data).
DATA(lv_parent_id) = ``.
ASSIGN COMPONENT lv_child_attribute
OF STRUCTURE ls_data
TO FIELD-SYMBOL(<lv_child_value>).
IF lv_parent_attribute IS NOT INITIAL.
ASSIGN COMPONENT lv_parent_attribute
OF STRUCTURE ls_data
TO FIELD-SYMBOL(<lv_parent_value>).
READ TABLE rt_result
INTO DATA(ls_parent)
WITH KEY
attribute = lv_parent_attribute
value = <lv_parent_value>.
lv_parent_id = ls_parent-id.
ENDIF.
READ TABLE rt_result
TRANSPORTING NO FIELDS
WITH KEY
attribute = lv_child_attribute
value = <lv_child_value>
parent_id = lv_parent_id.
IF sy-subrc <> 0.
INSERT VALUE #(
id = |{ lv_next_id }|
attribute = lv_child_attribute
value = <lv_child_value>
level = lv_level
parent_id = lv_parent_id )
INTO TABLE rt_result.
lv_next_id += 1.
ENDIF.
ENDLOOP.
lv_parent_attribute = lv_child_attribute.
ENDLOOP.
ENDMETHOD.
ENDCLASS.
Verified with the following unit test. It represents the example you gave:
CLASS ltc_unit_tests DEFINITION
FOR TESTING RISK LEVEL HARMLESS DURATION SHORT.
PRIVATE SECTION.
METHODS builds_example FOR TESTING.
ENDCLASS.
CLASS ltc_unit_tests IMPLEMENTATION.
METHOD builds_example.
DATA(lt_data) =
VALUE hierarchy_builder=>tt_input(
( color = 'green' producer = 'CompanyA' weight = '330' airplane = 'A350' )
( color = 'green' producer = 'CompanyA' weight = '222' airplane = 'A320' )
( color = 'green' producer = 'CompanyB' weight = '222' airplane = 'B450' )
( color = 'yellow' producer = 'CompanyA' weight = '330' airplane = 'H450' ) ).
DATA(lt_hierarchy) =
VALUE hierarchy_builder=>tt_attributes(
( `PRODUCER` )
( `WEIGHT` )
( `AIRPLANE` ) ).
DATA(lt_result) =
hierarchy_builder=>build_hierarchy(
it_data = lt_data
it_hierarchy = lt_hierarchy ).
DATA(lt_expected) =
VALUE hierarchy_builder=>tt_output(
( id = '1' attribute = 'PRODUCER' value = 'CompanyA' level = 1 parent_id = '' )
( id = '2' attribute = 'PRODUCER' value = 'CompanyB' level = 1 parent_id = '' )
( id = '3' attribute = 'WEIGHT' value = '330' level = 2 parent_id = '1' )
( id = '4' attribute = 'WEIGHT' value = '222' level = 2 parent_id = '1' )
( id = '5' attribute = 'WEIGHT' value = '222' level = 2 parent_id = '2' )
( id = '6' attribute = 'AIRPLANE' value = 'A350' level = 3 parent_id = '3' )
( id = '7' attribute = 'AIRPLANE' value = 'A320' level = 3 parent_id = '4' )
( id = '8' attribute = 'AIRPLANE' value = 'B450' level = 3 parent_id = '4' )
( id = '9' attribute = 'AIRPLANE' value = 'H450' level = 3 parent_id = '3' ) ).
cl_abap_unit_assert=>assert_equals(
act = lt_result
exp = lt_expected ).
ENDMETHOD.
ENDCLASS.