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

Loop on a internal table with data ref and a key

Former Member
0 Likes
7,177

Hi all,

this is my situation:

  1. I have a data reference to a sorted internal table lr_t_myTable;
  2. The sorted internal table has a non-unique primary key;
  3. I need to perform a loop on the internal table only on elements with key = "value1"

The "where" clause does not work because I have only the data reference or the field symbol of the original table.

A loop with an if inside is not feasible for performance reasons (the sorted table would become useless and it is really large).

How can I obtain this loop?

Thank you

1 ACCEPTED SOLUTION
Read only

SuhaSaha
Product and Topic Expert
Product and Topic Expert
0 Likes
4,691

Hello Alberto,

I think you can achieve this using RTTI & dynamic WHERE condition for LOOP. If your ABAP kernel does not support dynamic token for LOOP...WHERE, then i don't see this solution working.

  1. DATA:
  2.       flights_tab TYPE SORTED TABLE OF sflight WITH NON-UNIQUE KEY carrid.
  3. PARAMETERS:
  4.             p_carr TYPE sflight-carrid VALUE CHECK OBLIGATORY DEFAULT 'LH'.
  5. START-OF-SELECTION.
  6.   SELECT * FROM sflight INTO TABLE flights_tab.         "#EC CI_NOWHERE
  7.   GET REFERENCE OF flights_tab INTO DATA(tab_ref).
  8. * RTTI reads the data reference & gives us info regarding the keys
  9.   DATA(o_tab_desc) = CAST cl_abap_tabledescr( cl_abap_typedescr=>describe_by_data_ref( tab_ref ) ).
  10.   IF o_tab_desc->table_kind = cl_abap_tabledescr=>tablekind_sorted.
  11. *   For illustration purposes only, can use LOOP & build the dynamic condition accordingly
  12.     READ TABLE o_tab_desc->key ASSIGNING FIELD-SYMBOL(<key>) INDEX 1.
  13.     DATA(cond) = |{ <key>-name } = '{ p_carr }'|. "Build dynamic WHERE clause
  14.     TRY .
  15.         LOOP AT tab_ref->* ASSIGNING FIELD-SYMBOL(<wa>) WHERE (cond).
  16.           WRITE: / sy-tabix.
  17.         ENDLOOP.
  18.       CATCH cx_sy_itab_dyn_loop INTO DATA(o_excp).
  19.         MESSAGE o_excp->get_text( ) TYPE 'I'.
  20.     ENDTRY.
  21.   ENDIF.

In case you are not on ABAP 740, you'll have to change the code accordingly

BR,

Suhas

19 REPLIES 19
Read only

Former Member
0 Likes
4,691

one way, not most elegant but I have used approach before as it is only few lines of simple code and I just get the records I want to loop at

create a table copy, but as standard table...

then move all the data over...

data lt_standard type standard table of xyz.

lt_standard[] = lt_sorted[].

delete lt_standard where key ne 'VALUE1'.

loop at lt_standard assigning <fs>.

  ...do you work, updates, etc....

Read only

0 Likes
4,691

Hi Steve,

thank you for your answer.

However this is not a solution for me because:

  1. It requires 2 times the space of the original table;
  2. It is a sequential slow approach (does not exploit the sorted table)
  3. I am not able to know what is "xyz" (in your example)
Read only

0 Likes
4,691

It requires 2 times the space of the original table

? your copying the records from sorted to standard table. You will then remove all the records you dont want, and then wrok with the subset remaining!!!

It is a sequential slow approach (does not exploit the sorted table)

think again - you are just looping at the records you interested in using my way for records that equal VALUE1. Sequential is now irrelevant. I deleted all the records i did not want to loop through.

However, with your method - you are looping through a sorted table - this is still sequential - its only useful when you READ the table with a table key syntax doing it your way.

I am not able to know what is "xyz" (in your example)

come on, dont be silly - xyz is just a dummy reference name - it could be VBAK or whatever.

I will leave it here as I think you have not grasped what i was suggesting. I have used this technique a handful of times and it is fast. There are in fact several ways you can resolve your problem - but I just gave you a fast simple one.

Read only

0 Likes
4,691

Your method is really easy to understand. I think OP is dealing with dynamic table, and this is why he can't know in advance the value of "xyz". For the where clause to work, line type must be statically defined.

Read only

0 Likes
4,691

Hi Steve,

thank you again.

I will try to explain better my previous post:

1) It requires twice the original space because you are copying the original table. Suppose that the original table is 500MB, you will generate another 500MB of data and then remove some data. Generating 500MB of extra data and then removing a part of it is both time and memory consuming.

2) Sequential approach: yes, I would like to search records with the key using binary search, since I have a sorted table. Binary search is log(n) with n the number of records.

3) Of course I was not searching for "xyz", what I said is that I have only a reference to the original table as a "data ref". How can I get the type of the working area without using a dynamic allocation?

At the moment I solved the problem using a work around:

- I use READ... WITH KEY key='value1'

- I save the index returned by this reading operation;

- This index contains the first matching record.

- Inside a loop I check if the record with index+1 has the same key of the previous records.

- I continue to read the next record until the key is different.

This is possibile because I have a sorted table and I am filtering with the primary key.

Read only

0 Likes
4,691

It really is like the parallel cursor method. In case you are not already using the FROM index addition in LOOP statement, please add it. And exit the loop on first mismatch of key.

Read only

0 Likes
4,691

Hi Manish,

thank you.

So can I use the LOOP statement with FROM %index% clause and the loop will start from %index"?

At the moment I'm using a DO loop and checking the sy values. The LOOP statement would be better.

Read only

0 Likes
4,691

Yes you can. The INDEX addition does not work for hashed and any table types, but will work for sorted type.

Read only

SuhaSaha
Product and Topic Expert
Product and Topic Expert
0 Likes
4,692

Hello Alberto,

I think you can achieve this using RTTI & dynamic WHERE condition for LOOP. If your ABAP kernel does not support dynamic token for LOOP...WHERE, then i don't see this solution working.

  1. DATA:
  2.       flights_tab TYPE SORTED TABLE OF sflight WITH NON-UNIQUE KEY carrid.
  3. PARAMETERS:
  4.             p_carr TYPE sflight-carrid VALUE CHECK OBLIGATORY DEFAULT 'LH'.
  5. START-OF-SELECTION.
  6.   SELECT * FROM sflight INTO TABLE flights_tab.         "#EC CI_NOWHERE
  7.   GET REFERENCE OF flights_tab INTO DATA(tab_ref).
  8. * RTTI reads the data reference & gives us info regarding the keys
  9.   DATA(o_tab_desc) = CAST cl_abap_tabledescr( cl_abap_typedescr=>describe_by_data_ref( tab_ref ) ).
  10.   IF o_tab_desc->table_kind = cl_abap_tabledescr=>tablekind_sorted.
  11. *   For illustration purposes only, can use LOOP & build the dynamic condition accordingly
  12.     READ TABLE o_tab_desc->key ASSIGNING FIELD-SYMBOL(<key>) INDEX 1.
  13.     DATA(cond) = |{ <key>-name } = '{ p_carr }'|. "Build dynamic WHERE clause
  14.     TRY .
  15.         LOOP AT tab_ref->* ASSIGNING FIELD-SYMBOL(<wa>) WHERE (cond).
  16.           WRITE: / sy-tabix.
  17.         ENDLOOP.
  18.       CATCH cx_sy_itab_dyn_loop INTO DATA(o_excp).
  19.         MESSAGE o_excp->get_text( ) TYPE 'I'.
  20.     ENDTRY.
  21.   ENDIF.

In case you are not on ABAP 740, you'll have to change the code accordingly

BR,

Suhas

Read only

Former Member
0 Likes
4,691

You always use the inline data declaration, just to remind the rest of us that you are on ABAP 740 and we are not. Maybe i'll write a converter to make such statement backward compatible using search/replace

Read only

SuhaSaha
Product and Topic Expert
Product and Topic Expert
0 Likes
4,691

It is less showoff & more learning I need to get used to the 740 syntax & i'm luvin' it, isn't it cool?


Maybe i'll write a converter to make such statement backward compatible using search/replace

Be my guest

Read only

Former Member
0 Likes
4,691

Thank you Suhas,

I will try your code as soon as possible.

Inline data declaration looks great! However we have to develop our system on 731. We are migrating everything to 740 but for the moment we are on 731.

I will try your code, I understood the RTTI approach, however your code looks really close to my first attemp with a standard LOOP AT ... ASSIGNING ... WHERE. I can not understand why a dynamic (cond) works while my code did not work.

Also please could you expalin me how to write this line:

LOOP AT tab_ref->* ASSIGNING FIELD-SYMBOL(<wa>) WHERE (cond).

on 731? I'm not sure about the (cond) part.

Thank you

Read only

SuhaSaha
Product and Topic Expert
Product and Topic Expert
0 Likes
4,691

Hello Alberto,

I hope that you got the idea about what the code is doing, although it is written in 740 syntax.

You'll have to dereference the data reference before looping on it. This means another helper variable


   FIELD-SYMBOLS <tab>  TYPE SORTED TABLE.

   ASSIGN tab_ref->* TO <tab>.

   LOOP AT <tab> ASSIGNING <wa> WHERE (dyn_cond).

   ENDLOOP.

Good thing is that you are on ABAP 731 & dynamic WHERE is supported

BR,

Suhas

Read only

Former Member
0 Likes
4,691

Hi Sushas,

thank you, yes I got the idea.

My question is: will the dynamic WHERE clause search in the sorted table usin binary search or will it use a linear iteration?

Thank you

EDIT: this code is also working:

  DATA l_cond TYPE string VALUE 'FIELD1 = ''KEYVALUE1'''.

  LOOP AT <lt_myTable> INTO <ls_table> WHERE (l_cond).

    ....

  ENDLOOP.

But I'm not sure that it performs binary search on the sorted table using the key.

Read only

Former Member
0 Likes
4,691


I also found that this code is working:

  DATA l_cond TYPE string VALUE 'FIELD1 = ''KEYVALUE1'''.

  LOOP AT <lt_myTab> INTO <ls_tabRow> WHERE (l_cond).
    ...
  ENDLOOP.

But I'm not sure if it is using the binary search on the where statement.

Read only

SuhaSaha
Product and Topic Expert
Product and Topic Expert
0 Likes
4,691

Alberto Bedin wrote:

My question is: will the dynamic WHERE clause search in the sorted table usin binary search or will it use a linear iteration?

I had the same question yesterday. I checked the ABAP documentation & i don't see any thing which states that the LOOP...WHERE will not be optimized for dynamic condition I'm not sure if SAT/SE30 can be helpful

DATA l_cond TYPE string VALUE 'FIELD1 = ''KEYVALUE1'''

You can use this is you know that FIELD1 will always be the keyfield. In that case you do not need RTTI

BR,

Suhas

Read only

Former Member
0 Likes
4,691


Thank you. I think that I will check the dynamic WHERE performances on sorted tables and I will compare them with the READ statement followed by an index loop.

Read only

Former Member
0 Likes
4,691

I tested a TABLE of 10,000,000 records with 1000 matching keys:

  1. With a standard table and linear search (LOOP ... WHERE ... FROM field = 'value' )
  2. With a sorted table and LOOP ... WHERE ... FROM  key = 'value'
  3. With a sorted table and READ FROM ... WITH TABLE KEY ... followed by a LOOP FROM INDEX where index is the index of the first matching from READ statement.

The third approach is the fastest one (10-100) times faster. Incredibly the second approach is the slowest one (2 times slower then the first one). Maybe ABAP is performing multiple not optimized binary searches.

This result remain the same with any number of non-unique matching keys.

On the other side the second approach is faster on small tables (10000 elements).

Hope this could help.

Read only

Former Member
0 Likes
4,691

This message was moderated.