ABAP in Practice - Merge data sets
How do we merge two different data sets in ABAP, especially with regard to Modern ABAP? A practical task for this topic.
Table of contents
In a blog in the past we wrote about INSERT and how it will replace APPEND because it is more flexible and can be used in all situations. In this article we will look at a practical example.
Introduction
What is this example about? It is about a task of transferring two sets of data into a table and checking for duplicates because it is a sorted target table. We want to use only a little logic and work effectively in modern ABAP.
Preparation
First of all, we need two types that we want to merge together, but which are not completely the same. Both structures have a uniform identification (IDENT) and some flags that exist in both structures. One table type is a sorted table with a key, the other a standard table.
TYPES: BEGIN OF ts_unsorted,
ident TYPE i,
test1 TYPE abap_bool,
test2 TYPE abap_bool,
test3 TYPE abap_bool,
test4 TYPE abap_bool,
END OF ts_unsorted.
TYPES tt_unsorted TYPE STANDARD TABLE OF ts_unsorted WITH EMPTY KEY.
TYPES: BEGIN OF ts_sorted,
ident TYPE i,
test2 TYPE abap_bool,
test4 TYPE abap_bool,
test6 TYPE abap_bool,
END OF ts_sorted.
TYPES tt_sorted TYPE SORTED TABLE OF ts_sorted WITH UNIQUE KEY ident.
In the next step, we fill the two tables with random records to have some data. In this case, there is entry 3 in both tables, which is a duplicate.
DATA(lt_unsorted) = VALUE tt_unsorted(
( ident = 2 test1 = abap_true test2 = abap_true test3 = abap_false test4 = abap_true )
( ident = 3 test1 = abap_false test2 = abap_true test3 = abap_true test4 = abap_false )
( ident = 7 test1 = abap_true test2 = abap_false test3 = abap_true test4 = abap_true ) ).
DATA(lt_sorted) = VALUE tt_sorted( ( ident = 1 test2 = abap_false test4 = abap_true test6 = abap_false )
( ident = 3 test2 = abap_true test4 = abap_true test6 = abap_true )
( ident = 5 test2 = abap_false test4 = abap_false test6 = abap_true ) ).
Task
The task now is to merge the two tables. We have already transferred the sorted table into the RESULT and the data from the standard table still needs to be transferred. How would you go about it? Here you can find the complete class again so that you can transfer it to your system.
CLASS zcl_bs_demo_puzzle_02 DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
TYPES: BEGIN OF ts_unsorted,
ident TYPE i,
test1 TYPE abap_bool,
test2 TYPE abap_bool,
test3 TYPE abap_bool,
test4 TYPE abap_bool,
END OF ts_unsorted.
TYPES tt_unsorted TYPE STANDARD TABLE OF ts_unsorted WITH EMPTY KEY.
TYPES: BEGIN OF ts_sorted,
ident TYPE i,
test2 TYPE abap_bool,
test4 TYPE abap_bool,
test6 TYPE abap_bool,
END OF ts_sorted.
TYPES tt_sorted TYPE SORTED TABLE OF ts_sorted WITH UNIQUE KEY ident.
PRIVATE SECTION.
METHODS insert_into_sorted_data
IMPORTING it_unsorted TYPE tt_unsorted
it_sorted TYPE tt_sorted
RETURNING VALUE(rt_result) TYPE tt_sorted.
ENDCLASS.
CLASS zcl_bs_demo_puzzle_02 IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
DATA(lt_unsorted) = VALUE tt_unsorted(
( ident = 2 test1 = abap_true test2 = abap_true test3 = abap_false test4 = abap_true )
( ident = 3 test1 = abap_false test2 = abap_true test3 = abap_true test4 = abap_false )
( ident = 7 test1 = abap_true test2 = abap_false test3 = abap_true test4 = abap_true ) ).
DATA(lt_sorted) = VALUE tt_sorted( ( ident = 1 test2 = abap_false test4 = abap_true test6 = abap_false )
( ident = 3 test2 = abap_true test4 = abap_true test6 = abap_true )
( ident = 5 test2 = abap_false test4 = abap_false test6 = abap_true ) ).
out->write( insert_into_sorted_data( it_unsorted = lt_unsorted
it_sorted = lt_sorted ) ).
ENDMETHOD.
METHOD insert_into_sorted_data.
rt_result = it_sorted.
" Solution here
ENDMETHOD.
ENDCLASS.
Hint: In the next section we will go into the solution; if you want to do the task on your own, you should pause here.
Solution
We divide the solution into two suggestions. We will do the transfer in one step with as few statements as possible.
Suggestion 1 - Insert
In the first step, we will try a simple insert to transfer the data from one table to the target table.
- We will use CORRESPONDING to map to the different target structure.
- We must specify the type, otherwise we will get an error message from the compiler that the type cannot be derived.
- We want to use INSERT to correctly insert all rows of our table into the target table.
INSERT LINES OF CORRESPONDING tt_sorted( it_unsorted ) INTO TABLE rt_result.
This solution works quite well, but we get a corresponding abort if there are duplicate keys. The insert does not process the duplicates properly and still tries to transfer them to our target table.
Suggestion 2 - Corresponding
For the second solution we use the corresponding without an additional command. The first question that probably comes to mind is: Why use this command to transfer data records?
- We use the BASE addition of CORRESPONDING, so that in the first step we transfer the data records from the result into our new data set.
- Then we transfer the data records from our unsorted table.
- So that we do not receive an error message, we continue to use the DISCARD DUPLICATES addition to ignore duplicates.
rt_result = CORRESPONDING #( BASE ( rt_result ) it_unsorted DISCARDING DUPLICATES ).
What happened to our data set? First, the data set with identification 3 from the sorted table was taken and the data set from the unsorted data was ignored. You should pay particular attention to this rule when dealing with different data sets with different information.
Conclusion
There are different ways to find a solution, but you should also pay attention to the robustness of your code against errors. The first simple solution may work, but under special conditions it may cause unexpected errors.