In SAP, for better performance, instead of using nested loops, we can use the index looping technique.

The following sample code explains the usage of index looping and shows the difference between nested loops and index looping:


REPORT ZDEMOINDEXLOOPING.

*Internal tables and structures:
DATA:
  lt_bkpf     TYPE STANDARD TABLE OF bkpf,
  lt_bseg     TYPE STANDARD TABLE OF bseg,
  lst_bkpf    TYPE bkpf,
  lst_bseg    TYPE bseg.

*Variables:
DATA:
  gv_stime    TYPE i,         "Start Time
  gv_etime    TYPE i,         "End Time
  gv_tdiff    TYPE i,         "Time Difference
  gv_counter  TYPE i,         "Record Counter
  gv_tabix    TYPE sy-tabix.  "Tabix Position


*------------------------------------*
*DUMMY RETRIEVAL:                    *
*------------------------------------*
*Dummy retrieval for demo purposes.
*Data at header level.
SELECT *
  FROM bkpf
  INTO TABLE lt_bkpf
 UP TO 10 ROWS.

IF sy-subrc EQ 0.

* Sort and delete adjacent duplicates not necessary as
* we are sorting and deleting by primary keys. However, we
* will leave like that to remember that its a best practice
* to sort and delete adjacents duplicates when using for
* all entries.
  SORT lt_bkpf BY bukrs belnr gjahr.
  DELETE ADJACENT DUPLICATES FROM lt_bkpf COMPARING bukrs belnr gjahr.

ENDIF.

*If the table is not empty, proceed. Please note that
*this is necessary when doing for all entries because
*if the table 'LT_BKPF' is empty, the following retrieval
*will retrieve all the entries from table BSEG.
IF lt_bkpf[] IS NOT INITIAL.

* Data at item level.
  SELECT *
    FROM bseg
    INTO TABLE lt_bseg
 FOR ALL ENTRIES IN lt_bkpf
   WHERE bukrs EQ lt_bkpf-bukrs
     AND belnr EQ lt_bkpf-belnr
     AND gjahr EQ lt_bkpf-gjahr.

  IF sy-subrc EQ 0.

*     Sorting not required but its just for
*     information purposes.
    SORT lt_bseg BY bukrs belnr gjahr.

  ENDIF.

ENDIF.


*------------------------------------*
*NESTED LOOPS:                       *
*------------------------------------*
*Get the starting time.
GET RUN TIME FIELD gv_stime.

*Nested Loops:
*Loop at header level.
LOOP AT lt_bkpf INTO lst_bkpf.

* Loop at item level.
  LOOP AT lt_bseg INTO lst_bseg
  WHERE bukrs EQ lst_bkpf-bukrs
    AND belnr EQ lst_bkpf-belnr
    AND gjahr EQ lst_bkpf-gjahr.

*   Do some processing.
    gv_counter = gv_counter + 1.

  ENDLOOP.

ENDLOOP.

*Get the ending time.
GET RUN TIME FIELD gv_etime.

*Get the time difference, which will be the execution time
*the code was executed.
gv_tdiff = gv_etime - gv_stime.

*Output the time difference.
WRITE:/1(61) sy-uline.
WRITE: /1 sy-vline, 2(40) 'Taking Taken Using Nested Loops:', gv_tdiff,
                    41 sy-vline,
                    50(10) gv_tdiff,
                    61 sy-vline.

*------------------------------------*
*INDEX LOOPING:                      *
*------------------------------------*
CLEAR:
  gv_counter.

*Get the starting time.
GET RUN TIME FIELD gv_stime.

*Nested Loops:
*Loop at header level.
LOOP AT lt_bkpf INTO lst_bkpf.

* We will check if we have the header record
* at item level.
  READ TABLE lt_bseg
  TRANSPORTING NO FIELDS
  WITH KEY bukrs = lst_bkpf-bukrs
           belnr = lst_bkpf-belnr
           gjahr = lst_bkpf-gjahr
           BINARY SEARCH.

* If we have a match, get the tabix position
* at which we found the header level record in
* the item level table.
  IF sy-subrc EQ 0.

*   Get the tabix position of the line found
*   in 'LT_BSEG'. The tabix position will be
*   used to start the next loop at that position.
    gv_tabix = sy-tabix.

*   Loop at item level.
*   Here, we will start looping in the table 'LT_BSEG'
*   using the tabix position found above.
    LOOP AT lt_bseg INTO lst_bseg
    FROM gv_tabix.

*     Here, we will check if the current item level
*     record still match the header level record. If not,
*     means that we can exit the loop and take the next
*     header level record.
      IF lst_bkpf-bukrs NE lst_bseg-bukrs
      OR lst_bkpf-belnr NE lst_bseg-belnr
      OR lst_bkpf-gjahr NE lst_bseg-gjahr.

*       Clearing necessary items.
        CLEAR:
          gv_tabix,
          lst_bseg.

*       Okay, go out of the loop.
        EXIT.

      ENDIF.

*     If the IF statement above has failed, means that
*     that line at header level matches the line at item
*     level, do some processing.
*     Do some processing.
      gv_counter = gv_counter + 1.

*     Clearing necessary items.
      CLEAR:
        lst_bseg.

    ENDLOOP.

  ENDIF.

* Clearing necessary items.
  CLEAR:
    lst_bkpf.

ENDLOOP.

*Get the ending time.
GET RUN TIME FIELD gv_etime.

*Get the time difference, which will be the execution time
*the code was executed.
gv_tdiff = gv_etime - gv_stime.

*Output the time difference.
WRITE:/1(61) sy-uline.
WRITE: /1 sy-vline, 2(40) 'Taking Taken Using Index Looping:', gv_tdiff,
                    41 sy-vline,
                    50(10) gv_tdiff,
                    61 sy-vline.

WRITE:/1(61) sy-uline.



Serkan AKKAVAK
Computer Engineer
ABAP Developer & SAP S/4 HANA Logistics Consultant
Contact : serkurumsal@yandex.com