In this post, you will learn about LOOP AT… GROUP BY statement introduced in 7.40. This statement can be used instead of using AT NEW… END AT statements.

You can refer SCN wiki Control Level Statements in ABAP – ABAP Development – Community Wiki (sap.com) to learn about the AT… END AT control level statements.

In short, there are 4 AT statements which can be used inside a LOOP to produce summarization data.

  1. AT FIRST
    • Executed on the first record of the table
    • Can be used to write headers for report
  2. AT NEW <field>
    • Executed when the combination of fields up to the field mentioned after AT NEW changes
    • Can be used to initialize summarization data for the selected combination
  3. AT END OF <field>
    • Executed on the last entry of the combination of fields up to the field mentioned after AT END OF
    • Can be used to write the summarized data to internal table or screen / to call a BAPI
  4. AT LAST
    • Executed on the last record of the table
    • Clear / Free data tables

The control goes into the AT… ENDAT blocks as per below table.

For example, to print sum of total luggage weight per CARRID, CONNID, FLDATE combination using AT statements would look like below.

LOOP AT bookings INTO DATA(booking).
  AT FIRST.
    WRITE: 'Carrier', 9 'Connection', 21 'Flight Date'.
    ULINE.
  ENDAT.
  AT NEW fldate.
    CLEAR total_weight.
    WRITE: /  booking-carrid, 9 booking-connid,
           21 booking-fldate.
    WRITE: 35 'Customer Id', 50 'Luggage Weight'.
  ENDAT.

  WRITE: /35 booking-customid, 50 booking-luggweight.
  total_weight = total_weight + booking-luggweight.
 
  AT END OF fldate.
    WRITE: /35 'Total Weight : ', 50 total_weight.
    ULINE.
  ENDAT.
ENDLOOP.

The output is as below.

The same output can be achieved in ABAP 7.4 using the LOOP AT .. GROUP BY.

WRITE: 'Carrier', 9 'Connection', 21 'Flight Date'.
ULINE.
LOOP AT bookings INTO DATA(booking_gr)
                 GROUP BY ( carrid = booking_gr-carrid
                            connid = booking_gr-connid
                            fldate = booking_gr-fldate ).
  WRITE: /  booking_gr-carrid, 9 booking_gr-connid, 
         21 booking_gr-fldate.
  WRITE: 35 'Customer Id', 50 'Luggage Weight'.

  CLEAR total_weight.
  LOOP AT GROUP booking_gr 
                ASSIGNING FIELD-SYMBOL(<booking>).
    WRITE: /35 <booking>-customid, 50 <booking>-luggweight.
    total_weight = total_weight + <booking>-luggweight.
  ENDLOOP.

  WRITE: /35 'Total Weight : ', 50 total_weight.
  ULINE.
ENDLOOP.

For simplicity – let us look at the code without the write statements.

LOOP AT bookings INTO DATA(booking_gr)
                 GROUP BY ( carrid = booking_gr-carrid
                            connid = booking_gr-connid
                            fldate = booking_gr-fldate ).
 CLEAR total_weight.
 LOOP AT GROUP booking_gr ASSIGNING FIELD-SYMBOL(<booking>).
   total_weight = total_weight + <booking>-luggweight.
 ENDLOOP.
ENDLOOP.

This creates a deep structure booking_gr which has fields from the group by clause (carrid, connid, fldate) and the table entries which match this combination. To loop on this you need to use LOOP AT GROUP.

Variations – 

1. WITHOUT MEMBERS – Get unique values without requirement to loop on group members.

LOOP AT bookings INTO DATA(booking_gr)
                 GROUP BY ( carrid = booking_gr-carrid )
                 WITHOUT MEMBERS
                 REFERENCE INTO DATA(booking_gr_2).
  WRITE: / booking_gr_2->carrid.
ENDLOOP.

Note that a explicit reference is used to get the data. The output is as below.

2. Usage of MEMBERS, SIZE and INDEX

Here, you can get the index for the group and size of the group i.e. number of members in the group. Notice the sorting order specified. Default is ASCENDING.

LOOP AT bookings INTO DATA(booking_gr)
                 GROUP BY ( carrid = booking_gr-carrid
                            size   = GROUP SIZE
                            index  = GROUP INDEX )
                ASCENDING 
                REFERENCE INTO DATA(booking_gr_2).
  WRITE: / booking_gr_2->index LEFT-JUSTIFIED, 
          booking_gr_2->carrid, 
          booking_gr_2->size. 
ENDLOOP.

Output

So, by using LOOP AT… GROUP BY you can get rid of the AT statements, make the code cleaner. And unlike AT – you don’t need the fields used in combinations to be the first in the table structure.

For example, below will also work.

LOOP AT bookings INTO DATA(booking_gr)
                 GROUP BY ( customid = booking_gr-customid
                            size     = GROUP SIZE
                            index    = GROUP INDEX )
                 REFERENCE INTO DATA(booking_gr_2).
  WRITE: / booking_gr_2->customid, booking_gr_2->size.
ENDLOOP.

Read about more such ABAP expressions and exciting new syntaxes: ABAP Expressions (7.4+)


If you like the content, please subscribe…

Join 4,010 other subscribers

Discovering ABAP YouTube Channel