‎2020 Mar 03 5:53 AM
Hello,
I have to implement some parallel processing logic and therefore I have to create data packages of a defined package size.
Example from standard documentation ( Horst Keller ) makes first step easy.
With this coding packaging is quite easy
DATA(n) = 10.
cl_demo_input=>request( EXPORTING text = `Package size`
CHANGING field = n ).
IF n <= 0.
RETURN.
ENDIF.
cl_demo_output=>begin_section( |Packages of { n }| ).
DATA group LIKE itab.
LOOP AT itab INTO DATA(wa)
GROUP BY ( sy-tabix - 1 ) DIV n + 1.
CLEAR group.
LOOP AT GROUP wa ASSIGNING FIELD-SYMBOL(<wa>).
group = VALUE #( BASE group ( <wa> ) ).
ENDLOOP.
cl_demo_output=>write( group ).
ENDLOOP.
But I have an additional condition for this package building. I'm processing pricing conditions and when processing a package all parts of a pricing scale have to be in the same package.
Can I add an additional expression after statement.
GROUP BY ( sy-tabix - 1 ) DIV n + 1.
What statement can I use too keep pricing scales together in one package and at the same time skip correctly to next package ? ( It may so be possible that the package is smaller than package size n )
‎2020 Mar 03 9:42 AM
Please use the CODE button to format your code so that it's shown in a more user-friendly format (colorized).
‎2020 Mar 03 9:50 AM
Can you provide an example with input data and expected result?
‎2020 Mar 03 9:52 AM
For those persons interested, your example is taken from ABAP documentation - Internal Tables, Grouping with LOOP in Packages.
‎2020 Mar 03 8:58 PM
‎2020 Mar 04 12:38 AM
The taken example in your question to create packages does not depend on the row content. However, your requirement does also depend on the row content as well. And also your package size requirement makes it a little bit more complicated since a package is only allowed to be smaller but definitly not bigger.
I am assuming, you are wanting to use the GROUP BY function, because it looks more organized and is less coding, than programming the functions behind that logic yourself. Just be aware, that less coding does not necessarily also mean more performance.
And with your requirements, there are several things to be calculated and looked ahead in the group by condition. So you will end up with more coding again, one way or the other.
Before going into all possibilities with the GROUP BY parameter of the LOOP AT statement, you definitely could achieve the following with using a method (see Internal Tables, Grouping with LOOP Using a Method):
For point 2) I used a separate LOOP...GROUP BY... using column values and stored the calculated value in an appended field to the table (you could also have a reference table by key-id and store the calculated value there).
For point 3) I used the LOOP...GROUP BY... using a method to create the required packages. Note, that in case of keys with many duplicate key entries larger than the package size, those packages will end up being larger than package size, to avoid having to leave out those records. And there will be also packages with smaller package size, in case the next key with duplicate key entries does not fit into the current package.
CLASS demo DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
main,
class_constructor.
CLASS-DATA:
max_package_size TYPE int4 VALUE 4.
PRIVATE SECTION.
CLASS-DATA:
current_carrid TYPE spfli-carrid,
current_package TYPE int4 VALUE 1,
current_package_size TYPE int4,
BEGIN OF flight.
INCLUDE TYPE spfli.
CLASS-DATA: key_cnt TYPE int4,
END OF flight,
flights LIKE TABLE OF flight.
CLASS-METHODS
get_package IMPORTING flight LIKE flight
RETURNING VALUE(package) TYPE int4.
ENDCLASS.
CLASS demo IMPLEMENTATION.
METHOD main.
DATA(out) = cl_demo_output=>new( ).
DATA members LIKE flights.
LOOP AT flights INTO DATA(wa)
GROUP BY ( package = get_package( wa )
size = GROUP SIZE index = GROUP INDEX )
ASSIGNING FIELD-SYMBOL(<group>).
out->write( name = `Group key` data = <group> ).
CLEAR members.
LOOP AT GROUP <group> ASSIGNING FIELD-SYMBOL(<member>).
members = VALUE #( BASE members ( <member> ) ).
ENDLOOP.
out->write( members )->line( ).
ENDLOOP.
out->display( ).
ENDMETHOD.
METHOD class_constructor.
SELECT * FROM spfli INTO TABLE flights ORDER BY carrid.
LOOP AT flights INTO DATA(wa)
GROUP BY ( carrid = wa-carrid
size = GROUP SIZE index = GROUP INDEX )
ASSIGNING FIELD-SYMBOL(<group>).
LOOP AT GROUP <group> ASSIGNING FIELD-SYMBOL(<member>).
<member>-key_cnt = <group>-size.
ENDLOOP.
ENDLOOP.
ENDMETHOD.
METHOD get_package.
package = current_package.
IF current_carrid = flight-carrid.
ADD 1 TO current_package_size.
ELSE.
current_carrid = flight-carrid.
IF current_package_size >= max_package_size
OR current_package_size + flight-key_cnt > max_package_size.
ADD 1 TO: current_package, package.
current_package_size = 1.
ELSE.
ADD 1 TO current_package_size.
ENDIF.
ENDIF.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
demo=>main( ).
‎2020 May 13 3:09 PM
thomas.therre, please follow up on your open question.