Application Development and Automation Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

How to avoid complex looping?

former_member207873
Participant
0 Likes
1,340

Hi Experts,

My Scenario is like below. How can I avoid loop inside the loop.

I have to derive my final internal table from my first internal table (Say IT_VBRK2).

My internal table IT_VBRK2 looks like below.

VBELN  PSTYV     POSNR  FKIMG      LFIMG

30001    TAN       10                13            0

30001    YB99      900001         13           4

30001    YB99      900002         13           4

30001    YB99      900003         13           5

30002   TAN        10                 1              0

30002   TAN         20                1              0

30002   TAN         30                1              0

30002   YB99       900001         1              1

30002   YB99       900002         1              1

30002    YB99      900003         1              1

I need to manipulate my Final internal table from this and the logic is that,

> The rows with TAN values have to be header lines and the corresponding YB99 have to be item values.

> The logic for deciding the line items for a particular TAN is that...

    Consider VBELN - 30001----- Here the FKIMG of TAN is 13. So it has to be compared with the YB99 of the same VBELN. So for the first line of YB99 it is 4. which is less than 13. 13 > 4. Next line 13 > 4 + 4     . Next line 13 = 4 + 4+ 5. So the loop has to end there. So our final internal table has to have values like.

30001    TAN       10                13            0

30001    YB99      900001         13           4

30001    YB99      900002         13           4

30001    YB99      900003         13           5                     (Same as that of IT_VBRK2)

Now consider VBELN = 30002. and first line.

30002   TAN        10                 1              0. So we have to take the first corresponding YB99 value of the same VBELN.

30002   YB99       900001         1              1.

So here the TAN line FKIMG is 1 and YB99 line LFIMG = 1 ...So matching ..

So iterate to next TAN line and next corresponding YB99 line.

30002   TAN         20                1              0

30002   YB99       900001         1              1     TAN-FKIMG = YB99-LFIMG...So iterate to next line.

Like wise I need my final internal table like below.

30001    TAN       10                13            0

30001    YB99      900001         13           4

30001    YB99      900002         13           4

30001    YB99      900003         13           5

30002   TAN        10                 1              0

30002   YB99       900001         1              1

30002   TAN         20                1              0

30002   YB99       900002         1              1

30002   TAN         30                1              0

30002    YB99      900003         1              1


I got the output. But I had to use Loop inside loop and it is quite time consuming. (Even for one record it takes so much of time.) Can anyone please guide me to simpler solution. Here I am also attaching the psedo code. (The LOOP statements).







1 ACCEPTED SOLUTION
Read only

former_member129652
Active Participant
0 Likes
1,304

Hi,

  I notice that your final internal table and IT_VBRK2 have the same structure.  In other words, you just need a "re-ordering" of your IT_VBRK2.  Please try the following pseudo codes.

  1. Add a new field to IT_VBRK2. Let's call the new field "SORT_KEY".  The sort_key is type n of length 12. The first 6 characters indicate the TAN record, and the last 6 characters indicate the YB99 record.
    In your example,
    document 30001 item 10 has sort_key "000001000000".
    Document 30001 item 900001 has sort key "000001000001".
    Document 30001 item 900001 has sort key "000001000002".

  2. Sort IT_VBRK2 by VBELN PSTYV. The sorting must ensure that a TAN record is before all its corresponding YB99 records.

  3. In the loop, use 2 field symbols, 1 internal table of integers, and 1 integer.
    <FS_TAN> points to the current working TAN record.
    <FS_YB> points to the current working YB99 record.
    IT_TABIX_OF_TAN stores the tabix of the TAN records.
    LV_TABIX_OF_TAN is the tabix of the current working TAN record.

    You will also need a local vairable LV_REMAINING_QUANTITY which is the remaining quantity of your current working TAN record.

  4. You have to decide that you want IT_TABIX_OF_TAN to be a "stack" with "push" and "pop" operations, or a "queue" with "EN-queue" and "DE-queue" operations.  You can try both.  "Queue" and "stack" will give you opposite result.  I choose "stack".

  5. Loop through IT_VBRK2 INTO WA_VBRK2.

  6. If WA_VBRK2 is a TAN record, "push" the sy-tabix into "stack".

  7. If WA_VBRK2 is a YB99 record, then
    read table IT_VBRK2 assigning <FS_YB99> index sy-tabix.

  8. If <FS_TAN> is not assigned or LV_REMAINING_QUANTITY is less than <FS_YB>-FKIMG, then
    (8-1) "pop" 1 integer from "stack" and put the integer to LV_TABIX_OF_TAN.
    (8-2) read table IT_VBRK2 assigning <FS_TAN> index LV_TABIX_OF_TAN.
    (8-3) move <FS_TAN>-FKIMG to a local variable LV_REMAINING_QUANTITY.


  9. Calculate and modify <FS_YB>-FKIMG and <FS_YB>-LFIMG based on your business logic.
    Subtract <FS_YB>-LFIMG from LV_REMAINING_QUANTITY.

  10. Calculate <FS_TAN>-SORT_KEY and <FS_YB>-SORT_KEY.  Remember that the first 6 characters of <FS_TAN>-SORT_KEY and <FS_YB>-SORT_KEY are the same.

  11. If you reach a new billing document, then
    (11-1) clear the "stack" and LV_REMAINING_QUANTITY,
    (11-2) unassign field symbols.

  12. After loop, sort IT_VBRK2 by vbeln sort_key.

The complexity of the above loop is O(n), the complexity of sorting is O(n log n), and the complexity of "push" and "pop" is O(1).  The overall complexity is O(n log n).

As a final note, if your goal is to avoid nested loop, do NOT use "read table ... with key ..." inside your loop.  "Reading a standard table with key inside a loop" is actually a nested loop.

B.R.

10 REPLIES 10
Read only

former_member207873
Participant
0 Likes
1,304

Any help?

Read only

0 Likes
1,304

I believe that once u start xy questions

( like this one: )

and do never close them or give any feedback, people will just stop trying to help you

Read only

0 Likes
1,304

Hi

Let me explain you what happened. In my previous discussion as you have mentioned.  How to avoid loop inside loop?I tried to save what ever I have written. Then it got posted automatically. Then I tried to edit the same , but the result was an error page. I couldnt complete the question and the option to edit also disappeared by this time. Then the only option left before me was to close that thread by assuming the answer and start a new one. I think you got my point. Please do not take anything  negative.

BR.

Read only

0 Likes
1,304

It's ok. people just often get frustrated when not gettin' any feedback.

to your problem - once you would like to increase the performance and get rid of inner loops, use the inner join in your select.

But from what you wrote, it seems that the logic you need is not implementable using a simple select (or OpenSQL). If your main problem is performance, do these steps first:

1. get rid of work-areas, use field-symbols instead

2. think of use of your internal tables and imagine if you can use sorted table instead of standard table, in read statements use binary search on sorted tables. You will find huge speed increase.

3++ ... if you want to optimize the code, you will find many articles even here, just search. If you need a concrete hint, try to narrow your question to a simpler one, it is much easier to answer then.

Read only

0 Likes
1,304

Not really understand the logic, what I can help is just optimize your code to boost up the performance:

SORT IT_TVKBT2 BY VKBUR.

SORT IT_TSPAT2 BY SPART.

SORT IT_KNA12 BY KUNNR.

LOOP AT IT_VBRK2 INTO WA_VBRK2.

   IF  WA_VBRK2-VGPOS = WA_VBRK2-LPOSNR AND

       WA_VBRK2-VGBEL = WA_VBRK2-LVBELN AND

       WA_VBRK2-MATNR = WA_VBRK2-LMATNR AND

       WA_VBRK2-FKIMG = WA_VBRK2-LFIMG.      "Manual Batch

     WA_FINALDET-FKDAT = WA_VBRK2-FKDAT.

     WA_FINALDET-SPART = WA_VBRK2-SPART.

     WA_FINALDET-NETWR = WA_VBRK2-NETWR.

     WA_FINALDET-KUNAG = WA_VBRK2-KUNAG.

     WA_FINALDET-KUNRG = WA_VBRK2-KUNRG.

     WA_FINALDET-SFAKN = WA_VBRK2-SFAKN.

     WA_FINALDET-VBELN = WA_VBRK2-VBELN.

     WA_FINALDET-LVBELN = WA_VBRK2-LVBELN.

*    wa_finaldet-erdat = wa_vbrk2-erdat.

     WA_FINALDET-VKBUR = WA_VBRK2-VKBUR.

     WA_FINALDET-POSNR = WA_VBRK2-POSNR.

     WA_FINALDET-CHARG = WA_VBRK2-CHARG.

     WA_FINALDET-MATNR = WA_VBRK2-MATNR.

     WA_FINALDET-ARKTX = WA_VBRK2-ARKTX.

     WA_FINALDET-FKIMG = WA_VBRK2-FKIMG.

     WA_FINALDET-VRKME = WA_VBRK2-VRKME.

     WA_FINALDET-ORDER_NUM = WA_VBRK2-POSNR.

     READ TABLE IT_TVKBT2 INTO WA_TVKBT2 WITH KEY VKBUR = WA_VBRK2-VKBUR BINARY SEARCH.

     IF SY-SUBRC = 0.

       WA_FINALDET-BEZEI = WA_TVKBT2-BEZEI.

     ENDIF.

     READ TABLE IT_TSPAT2 INTO WA_TSPAT2 WITH KEY SPART = WA_VBRK2-SPART BINARY SEARCH.

     IF SY-SUBRC = 0.

       WA_FINALDET-VTEXT = WA_TSPAT2-VTEXT.

     ENDIF.

     READ TABLE IT_KNA12 INTO WA_KNA12 WITH KEY KUNNR = WA_VBRK2-KUNAG BINARY SEARCH.

     IF SY-SUBRC = 0.

       WA_FINALDET-NAME1 = WA_KNA12-NAME1.

       WA_FINALDET-NAME2 = WA_KNA12-NAME1.

     ENDIF.

     APPEND WA_FINALDET TO IT_FINALDET.

     CLEAR WA_FINALDET.

     CONTINUE.

   ENDIF.

   IF WA_VBRK2-VGPOS = WA_VBRK2-LPOSNR AND

      WA_VBRK2-VGBEL = WA_VBRK2-LVBELN AND

      WA_VBRK2-MATNR = WA_VBRK2-LMATNR AND                  "    Automatic Batch        First I am taking the all the TAN values to the final internal table.

      WA_VBRK2-PSTYV = 'TAN'.

     WA_FINALDET-FKDAT = WA_VBRK2-FKDAT.

     WA_FINALDET-SPART = WA_VBRK2-SPART.

     WA_FINALDET-NETWR = WA_VBRK2-NETWR.

     WA_FINALDET-KUNAG = WA_VBRK2-KUNAG.

     WA_FINALDET-KUNRG = WA_VBRK2-KUNRG.

     WA_FINALDET-SFAKN = WA_VBRK2-SFAKN.

     WA_FINALDET-VBELN = WA_VBRK2-VBELN.

     WA_FINALDET-SORT_KEY = ''.

     WA_FINALDET-LVBELN = WA_VBRK2-LVBELN.

*    wa_finaldet-erdat = wa_vbrk2-erdat.

     WA_FINALDET-VKBUR = WA_VBRK2-VKBUR.

     WA_FINALDET-POSNR = WA_VBRK2-POSNR.

     WA_FINALDET-CHARG = WA_VBRK2-CHARG.

     WA_FINALDET-MATNR = WA_VBRK2-MATNR.

     WA_FINALDET-ARKTX = WA_VBRK2-ARKTX.

     WA_FINALDET-FKIMG = WA_VBRK2-FKIMG.

     WA_FINALDET-VRKME = WA_VBRK2-VRKME.

     WA_FINALDET-ORDER_NUM = WA_VBRK2-POSNR.

     READ TABLE IT_TVKBT2 INTO WA_TVKBT2 WITH KEY VKBUR = WA_VBRK2-VKBUR BINARY SEARCH.

     IF SY-SUBRC = 0.

       WA_FINALDET-BEZEI = WA_TVKBT2-BEZEI.

     ENDIF.

     READ TABLE IT_TSPAT2 INTO WA_TSPAT2 WITH KEY SPART = WA_VBRK2-SPART BINARY SEARCH.

     IF SY-SUBRC = 0.

       WA_FINALDET-VTEXT = WA_TSPAT2-VTEXT.

     ENDIF.

     READ TABLE IT_KNA12 INTO WA_KNA12 WITH KEY KUNNR = WA_VBRK2-KUNAG BINARY SEARCH.

     IF SY-SUBRC = 0.

       WA_FINALDET-NAME1 = WA_KNA12-NAME1.

       WA_FINALDET-NAME2 = WA_KNA12-NAME1.

     ENDIF.

*    TEMP_VGPOS = WA_VBRK2-VGPOS.

*    TEMP_VGBEL = WA_VBRK2-VGBEL.

     APPEND WA_FINALDET TO IT_FINALDET.

     CLEAR WA_FINALDET.

   ENDIF.

ENDLOOP.

DATA: TEMP_LFIMG TYPE LFIMG,

       TEMP_FKIMG TYPE FKIMG,

       TEMP_FINDET TYPE STANDARD TABLE OF TY_FINALDET,

       WA_TEMP_FINDET LIKE LINE OF TEMP_FINDET,

       COUNT TYPE I.

SORT IT_VBRK2 BY VBELN MATNR PSTYV LFIMG PROC_KEY.

LOOP AT IT_FINALDET INTO WA_FINALDET WHERE PROC_KEY NE 'X'.

   TEMP_FKIMG = WA_FINALDET-FKIMG.

   READ TABLE IT_VBRK2 TRANSPORTING NO FIELDS WITH TABLE KEY VBELN = WA_FINALDET-VBELN MATNR = WA_FINALDET-MATNR PSTYV = 'YB99' BINARY SEARCH.

   IF SY-SUBRC EQ 0.

     LOOP AT IT_VBRK2 INTO WA_VBRK2 FROM SY-TABIX.

       "(LOOP INSIDE LOOP ...THIS IS WHAT I WANT TO AVOID)

       IF WA_VBRK2-LFIMG EQ WA_FINALDET-FKIMG.

         CONTINUE.

       ENDIF.

       IF WA_VBRK2-VBELN NE WA_FINALDET-VBELN OR WA_VBRK2-MATNR NE WA_FINALDET-MATNR OR WA_VBRK2-PSTYV NE 'YB99'.

         EXIT.

       ENDIF.

       TEMP_LFIMG = TEMP_LFIMG + WA_VBRK2-LFIMG.

       IF TEMP_LFIMG LE TEMP_FKIMG.

         WA_FINALDET-FKDAT = WA_VBRK2-FKDAT.

         WA_FINALDET-SPART = WA_VBRK2-SPART.

         WA_FINALDET-NETWR = WA_VBRK2-NETWR.

         WA_FINALDET-KUNAG = WA_VBRK2-KUNAG.

         WA_FINALDET-KUNRG = WA_VBRK2-KUNRG.

         WA_FINALDET-SFAKN = WA_VBRK2-SFAKN.

         WA_FINALDET-VBELN = WA_VBRK2-VBELN.

         WA_FINALDET-SORT_KEY = 'A'.

         WA_FINALDET-LVBELN = WA_VBRK2-LVBELN.

*    wa_finaldet-erdat = wa_vbrk2-erdat.

         WA_FINALDET-VKBUR = WA_VBRK2-VKBUR.

         WA_FINALDET-POSNR = WA_VBRK2-POSNR.

         WA_FINALDET-CHARG = WA_VBRK2-CHARG.

         WA_FINALDET-MATNR = WA_VBRK2-MATNR.

         WA_FINALDET-ARKTX = WA_VBRK2-ARKTX.

         WA_FINALDET-FKIMG = WA_VBRK2-FKIMG.

         WA_FINALDET-VRKME = WA_VBRK2-VRKME.

         WA_FINALDET-ORDER_NUM = WA_VBRK2-LPOSNR.

         WA_FINALDET-PROC_KEY = 'X'.

         READ TABLE IT_TVKBT2 INTO WA_TVKBT2 WITH KEY VKBUR = WA_VBRK2-VKBUR BINARY SEARCH.

         IF SY-SUBRC = 0.

           WA_FINALDET-BEZEI = WA_TVKBT2-BEZEI.

         ENDIF.

         READ TABLE IT_TSPAT2 INTO WA_TSPAT2 WITH KEY SPART = WA_VBRK2-SPART BINARY SEARCH.

         IF SY-SUBRC = 0.

           WA_FINALDET-VTEXT = WA_TSPAT2-VTEXT.

         ENDIF.

         READ TABLE IT_KNA12 INTO WA_KNA12 WITH KEY KUNNR = WA_VBRK2-KUNAG BINARY SEARCH.

         IF SY-SUBRC = 0.

           WA_FINALDET-NAME1 = WA_KNA12-NAME1.

           WA_FINALDET-NAME2 = WA_KNA12-NAME1.

         ENDIF.

         APPEND WA_FINALDET TO IT_FINALDET.

         CLEAR WA_FINALDET.

       ENDIF.

     ENDLOOP.

   ENDIF.

   READ TABLE IT_VBRK2 INTO WA_VBRK2 WITH KEY VBELN = WA_FINALDET-VBELN MATNR = WA_FINALDET-MATNR

   PSTYV = 'YB99' LFIMG = WA_FINALDET-FKIMG PROC_KEY = '' BINARY SEARCH.

   IF SY-SUBRC = 0 .

     WA_FINALDET-FKDAT = WA_VBRK2-FKDAT.

     WA_FINALDET-SPART = WA_VBRK2-SPART.

     WA_FINALDET-NETWR = WA_VBRK2-NETWR.

     WA_FINALDET-KUNAG = WA_VBRK2-KUNAG.

     WA_FINALDET-KUNRG = WA_VBRK2-KUNRG.

     WA_FINALDET-SFAKN = WA_VBRK2-SFAKN.

     WA_FINALDET-VBELN = WA_VBRK2-VBELN.

     WA_FINALDET-SORT_KEY = 'A'.

     WA_FINALDET-LVBELN = WA_VBRK2-LVBELN.

*    wa_finaldet-erdat = wa_vbrk2-erdat.

     WA_FINALDET-VKBUR = WA_VBRK2-VKBUR.

     WA_FINALDET-POSNR = WA_VBRK2-POSNR.

     WA_FINALDET-CHARG = WA_VBRK2-CHARG.

     WA_FINALDET-MATNR = WA_VBRK2-MATNR.

     WA_FINALDET-ARKTX = WA_VBRK2-ARKTX.

     WA_FINALDET-FKIMG = WA_VBRK2-FKIMG.

     WA_FINALDET-VRKME = WA_VBRK2-VRKME.

     WA_FINALDET-PROC_KEY = 'X'.

*    WA_FINALDET-ORDER_NUM =

     READ TABLE IT_TVKBT2 INTO WA_TVKBT2 WITH KEY VKBUR = WA_VBRK2-VKBUR BINARY SEARCH.

     IF SY-SUBRC = 0.

       WA_FINALDET-BEZEI = WA_TVKBT2-BEZEI.

     ENDIF.

     READ TABLE IT_TSPAT2 INTO WA_TSPAT2 WITH KEY SPART = WA_VBRK2-SPART BINARY SEARCH.

     IF SY-SUBRC = 0.

       WA_FINALDET-VTEXT = WA_TSPAT2-VTEXT.

     ENDIF.

     READ TABLE IT_KNA12 INTO WA_KNA12 WITH KEY KUNNR = WA_VBRK2-KUNAG BINARY SEARCH.

     IF SY-SUBRC = 0.

       WA_FINALDET-NAME1 = WA_KNA12-NAME1.

       WA_FINALDET-NAME2 = WA_KNA12-NAME1.

     ENDIF.

*   WA_TEMP_FINDET-ORDER_NUM = SY-TABIX.

     APPEND WA_FINALDET TO IT_FINALDET.

*    CLEAR WA_TEMP_FINDET.

     WA_VBRK2-PROC_KEY = 'X'.

     MODIFY IT_VBRK2 FROM WA_VBRK2 INDEX SY-TABIX TRANSPORTING PROC_KEY.

   ENDIF.

   CLEAR: TEMP_LFIMG, TEMP_FKIMG.

ENDLOOP.

Read only

0 Likes
1,304

Hi Jozef Vaclavek

Thanks for your reply. I know it is a bit difficult to understand. Let me try to make it simpler. Suppose I have to loop through an internal table to get the final internal table.

Suppose this particular line of data in my first internal table.

30001    TAN       10                13            0.  -> Corresponds to many lines of data, for that i have to use loop                                                                                         inside loop. So no read statement possible.

Consider another line of data.


30002    TAN       10                1            1     -> This particlar line of data only corresponds to one line of data. So

                                                                              I can use read statement.


Is there any way of avoiding loop inside loop?


BR.






Read only

0 Likes
1,304

you always can change a loop statement with something like

do.

     read....

     if     (sy-subrc <> 0 )

          exit.

     endif.

enddo.

But this would not be ok in your case. Please, use sorted tables (not sorted like sort abcd by xyz, but data: lt_table type sorted table...

This will improve your performance a lot.

Read only

0 Likes
1,304

is your problem solved already?

Read only

former_member129652
Active Participant
0 Likes
1,305

Hi,

  I notice that your final internal table and IT_VBRK2 have the same structure.  In other words, you just need a "re-ordering" of your IT_VBRK2.  Please try the following pseudo codes.

  1. Add a new field to IT_VBRK2. Let's call the new field "SORT_KEY".  The sort_key is type n of length 12. The first 6 characters indicate the TAN record, and the last 6 characters indicate the YB99 record.
    In your example,
    document 30001 item 10 has sort_key "000001000000".
    Document 30001 item 900001 has sort key "000001000001".
    Document 30001 item 900001 has sort key "000001000002".

  2. Sort IT_VBRK2 by VBELN PSTYV. The sorting must ensure that a TAN record is before all its corresponding YB99 records.

  3. In the loop, use 2 field symbols, 1 internal table of integers, and 1 integer.
    <FS_TAN> points to the current working TAN record.
    <FS_YB> points to the current working YB99 record.
    IT_TABIX_OF_TAN stores the tabix of the TAN records.
    LV_TABIX_OF_TAN is the tabix of the current working TAN record.

    You will also need a local vairable LV_REMAINING_QUANTITY which is the remaining quantity of your current working TAN record.

  4. You have to decide that you want IT_TABIX_OF_TAN to be a "stack" with "push" and "pop" operations, or a "queue" with "EN-queue" and "DE-queue" operations.  You can try both.  "Queue" and "stack" will give you opposite result.  I choose "stack".

  5. Loop through IT_VBRK2 INTO WA_VBRK2.

  6. If WA_VBRK2 is a TAN record, "push" the sy-tabix into "stack".

  7. If WA_VBRK2 is a YB99 record, then
    read table IT_VBRK2 assigning <FS_YB99> index sy-tabix.

  8. If <FS_TAN> is not assigned or LV_REMAINING_QUANTITY is less than <FS_YB>-FKIMG, then
    (8-1) "pop" 1 integer from "stack" and put the integer to LV_TABIX_OF_TAN.
    (8-2) read table IT_VBRK2 assigning <FS_TAN> index LV_TABIX_OF_TAN.
    (8-3) move <FS_TAN>-FKIMG to a local variable LV_REMAINING_QUANTITY.


  9. Calculate and modify <FS_YB>-FKIMG and <FS_YB>-LFIMG based on your business logic.
    Subtract <FS_YB>-LFIMG from LV_REMAINING_QUANTITY.

  10. Calculate <FS_TAN>-SORT_KEY and <FS_YB>-SORT_KEY.  Remember that the first 6 characters of <FS_TAN>-SORT_KEY and <FS_YB>-SORT_KEY are the same.

  11. If you reach a new billing document, then
    (11-1) clear the "stack" and LV_REMAINING_QUANTITY,
    (11-2) unassign field symbols.

  12. After loop, sort IT_VBRK2 by vbeln sort_key.

The complexity of the above loop is O(n), the complexity of sorting is O(n log n), and the complexity of "push" and "pop" is O(1).  The overall complexity is O(n log n).

As a final note, if your goal is to avoid nested loop, do NOT use "read table ... with key ..." inside your loop.  "Reading a standard table with key inside a loop" is actually a nested loop.

B.R.

Read only

Former Member
0 Likes
1,304

Hi,

Post the select & statements that you generate the final internal table. There should be some other linking between the header & line items. Please explain why such a mathematical relation between them?

Thanks,

Shajahan.