Reputation: 123
Suppose I have 2 internal tables:
TYPES:BEGIN OF LTY_FILE,
SOKEY TYPE CHAR5,
SOPONO TYPE CHAR15,
SOCONO TYPE CHAR15,
FLAG TYPE C,
END OF LTY_FILE.
data:IT_ARCHIVE TYPE TABLE OF LTY_FILE,
IT_SAP TYPE TABLE OF LTY_FILE.
it_archive = VALUE #(
( sokey = 'Key1' sopono = 'PO#12' socono = 'Three' flag = 'A' )
( sokey = 'Key2' sopono = 'PO#34' socono = 'Four' flag = 'B' ) ).
it_sap = VALUE #(
( sokey = 'Key1' sopono = 'PO#12' socono = 'Three' flag = 'A' ) ).
IT_ARCHIVE
:
SOKEY | SOPONO | SOCONO | FLAG |
---|---|---|---|
Key1 | PO#12 | Three | A |
Key2 | PO#34 | Four | B |
IT_SAP
:
SOKEY | SOPONO | SOCONO | FLAG |
---|---|---|---|
Key1 | PO#12 | Three | A |
Now I want the lines from IT_ARCHIVE
which don't exist in IT_SAP
, based on keys SOKEY
, SOPONO
and SOCONO
, to be added to IT_SAP
with FLAG = D
:
SOKEY | SOPONO | SOCONO | FLAG |
---|---|---|---|
Key2 | PO#34 | Four | B |
So, new IT_SAP
should look like:
SOKEY | SOPONO | SOCONO | FLAG |
---|---|---|---|
Key1 | PO#12 | Three | A |
Key2 | PO#34 | Four | D |
Until now, I have tried following ways,but failed in ABAP 7.4, but as the data is quite huge (more than 400K in each run), I am looking for performance centric code to achieve this.
DATA(ls_wa) = it_sap[ 1 ]. " Temporary workarea for insertion.
CLEAR:ls_wa
LOOP AT IT_ARCHIVE ASSIGNING FIELD SYMBOL(<lfs_archive>).
IF NOT LINE_EXISTS( it_sap[ sokey = <lfs_Archive>-sokey
sopono = <lfs_Archive>-sopono
socono = <lfs_archive>-socono ] ).
ls_wa = <lfs_archive>.
ls_wa-flag = 'D'.
APPEND ls_wa to IT_SAP.
CLEAR:ls_wa.
ENDIF.
ENDLOOP.
Second approach I tried:
data(LT_FINAL) = IT_SAP[].
REFRESH:LT_FINAL[].
lt_final = VALUE #( FOR ls_ar IN IT_ARCHIVE
FOR ls_sap IN IT_SAP WHERE ( sokey <> <lfs_Archive>-sokey
sopono <> <lfs_Archive>-sopono
socono <> <lfs_archive>-socono )
(
"Explicitly mentioning all fields as have to change FLAG value
sokey = ls_Ar-sokey
sopono = ls_ar-sopono
socono = ls_ar-socono
flag = 'D'
) ).
The first approach, takes too much of time as have huge number of data. The second approach, to my surprise is not giving me the same result as the first one.
Is there any better way in ABAP 7.4+ to achieve this?
Upvotes: 3
Views: 7273
Reputation: 13646
Your main question is about performance. For information, there are other alike questions/answers in Stack Overflow concerning performance and internal tables.
In your case, you use "standard" table types (DATA ... TYPE TABLE OF ...
), so each lookup (line_exists
) will look at all lines of the internal table until one is found. Instead of looking at all the lines again and again, it's best to sort once the internal table, and each lookup will be much faster; that's easy to understand why: if you, human, look at a word in a dictionary (book), hopefully the words are sorted and you will quickly find this word (providing that you know the order of letters A, B, C, etc.; it's the same for a computer.
There are two ways to sort the internal table:
SORT
. This option is simpler to understand but highly not recommended whenever possible.To choose between sorted and hashed (i.e. for implicit sorting), you must simply know if it's possible to have two same lines with the exact same key.
In your case, just doing that declaration below would dramatically improve the performance of your current (working) algorithm:
TYPES:BEGIN OF lty_file,
sokey TYPE char5,
sopono TYPE char15,
socono TYPE char15,
flag TYPE c,
END OF lty_file.
TYPES:lty_file_tab TYPE SORTED TABLE OF lty_file WITH NON-UNIQUE KEY sokey sopono socono.
DATA:it_archive TYPE lty_file_tab,
it_sap TYPE lty_file_tab.
You may also improve a little bit your algorithm by using the built-in operator FILTER
which I think runs more in the kernel (more information about FILTER
in the answer of this other question).
For instance:
it_sap = VALUE #(
BASE it_sap
( LINES OF VALUE #( FOR <line> IN
FILTER #( it_archive EXCEPT IN it_sap
WHERE sokey = sokey
AND sopono = sopono
AND socono = socono )
( VALUE #( BASE <line> flag = 'D' ) ) ) ) ).
ASSERT it_sap = VALUE lty_file_tab(
( sokey = 'Key1' sopono = 'PO#12' socono = 'Three' flag = 'A' )
( sokey = 'Key2' sopono = 'PO#34' socono = 'Four' flag = 'D' ) ).
(NB: I use ASSERT
here just to prove that the internal table has the indicated value; otherwise that would stop the program/raise a runtime error)
Upvotes: 7