‎2009 Oct 16 7:43 PM
Hi guys!
Please, what can i do when i use the
Read table xxxx WITH KEY tab_key = value ASSIGNING <fs>
statement and there is more than one entry with the specified selection criteria? How can i return the values to an internal table?
I need to get all the entries and i don't have the full table key.
thanks!
‎2009 Oct 16 8:07 PM
One method is shown here:
[The Performance of Nested Loops|/people/rob.burbank/blog/2006/02/07/performance-of-nested-loops]
Rob
‎2009 Oct 16 8:07 PM
One method is shown here:
[The Performance of Nested Loops|/people/rob.burbank/blog/2006/02/07/performance-of-nested-loops]
Rob
‎2009 Oct 16 8:41 PM
Hi Fabio...
You cannt retrieve more than one row using READ TABLE. You have to use a LOOP - ENDLOOP statement in order to get each row of your table that fulfill your condition, and append them to your new table.
Write if you need more info.
Dimas Salazar
Caracas - Venezuela
‎2009 Oct 16 10:33 PM
Hi Fabio,
An efficient way to do this is to have your table sorted by a specific key. Let's say I have a table with the feild material number.
You can do this:
data: lv_index like sy-tabix.
sort itab by material_number.
ready table itab with key material_number = yournumber
binary search.
if sy-subrc eq 0.
move sy-tabix to lv_index. " this holds the index of your first material record
now we loop at the table start at that index
loop at itab index lv_index.
perform your processing
if we come accross a different material number - exit the loop.
if itab-material_number ne yournumber.
exit.
endif.
endloop.
endif.
This way you only processes the records you are looking for.
thanks.
JB
‎2009 Oct 16 10:37 PM
But you process the first one twice. How wouild you get around that.
Rob
‎2009 Oct 17 2:51 AM
Hi,
If you are concerned about processing the first record twice. You can just add one to the index before you start looping.
thanks.
JB
‎2009 Oct 17 2:52 AM
In my example the read is only used to find the index, but you could process the first record at this time, add one to the index and then start looping.
thanks.
JB
‎2009 Oct 18 11:23 AM
thanks for the replies.
i'll test some scenarios and then return back.
At the moment i'm wondering if binary search would always return the first line in the criteria.
See you soon.
‎2009 Oct 19 3:09 PM
>
> At the moment i'm wondering if binary search would always return the first line in the criteria.
> See you soon.
No, it will not.
‎2009 Oct 19 3:28 PM
Rainer - from the help for READ with BINARY SEARCH:
> if there are several hits (because of an incompletely specified search key or because there are
> duplicate entries in the table), then the first hit in terms of the sequence of the rows is always
> returned, that is, the row with the smallest index.
Rob
‎2009 Oct 19 3:54 PM
Ok, didnt know that cause a binary search itself will not position on the first row (row with lowest index). If you have 5 rows with the same key, it will give you back the second or third index depending on the algorithm.
So in ABAP there must be an additional "read back until" to get the row with the lowest index.
‎2009 Oct 19 5:33 PM
yes.. probably is that... good to know it.
this thread is going deep, that's cool!
i already start a resolution without using the where clause.. after i'll do using that and post my results too. Then i check this thread answered.
thanks to everybody.
‎2010 Jan 08 2:05 AM
Hi guys! after a long time I'm back to post the results.
Rob Burbank was very helpful and the solution was create nested loops using read table binary search and then start the 'inside' loops from the found index.
a friend of mine told me this technique is called 'binary loop'. It has a really good performance and don't create internal tables like the where condition in the loop statement.
thanks for everybody!
‎2009 Oct 17 7:03 AM
Hello Fabio
Unfortunately ABAP doesn't provide any means to just read multiple line from one internal table to other. So you can not use READ TABLE for your purpose.
You will have to use LOOP... ENDLOOP only. You can use the following construct:
LOOP AT XXX ASSIGNING <fs>.
CHECK <fs>-tabkey = value.
..... Process <fs>......
ENDLOOP.I didnt suggest the WHERE clause in LOOP statement because its very non-performant. So better check your condition inside with CHECK statement. If CHECK fails, the loop will continue with the next iteration.
Thanks and Regards
Anand.
[How2SAP.com|http://www.how2sap.com/]
‎2009 Oct 17 8:56 PM
Anand - you can read every record in an internal table and never use a LOOP statement.
Why do you say that the CHECK is better than using LOOP...WHERE? If you can show an example with run time statistics, that would be great.
Rob
‎2009 Oct 18 1:15 PM
>
> Anand - you can read every record in an internal table and never use a LOOP statement.
>
> Why do you say that the CHECK is better than using LOOP...WHERE? If you can show an example with run time statistics, that would be great.
>
> Rob
As I understand it, WHERE is usually better performance-wise.
‎2009 Oct 18 8:13 PM
>
> As I understand it, WHERE is usually better performance-wise.
I would expect that they do basically the same thing, but I'll try to check it Monday or Tuesday.
Rob
‎2009 Oct 19 3:44 AM
Hi Fabio,
<li>READ TABLE statement does not return multiple values as you said.
<li>Use LOOP -ENDLOOP statement by setting WHERE clause also. It gives good results when you multiple records for the condition given .
READ TABLE sflight_tab
WITH TABLE KEY carrid = p_carrid
fldate = p_fldate
ASSIGNING <sflight>.
Thanks
Venkat.OLOOP AT sflight_tab ASSIGNING <sflight> WHERE carrid = p_carrid
AND fldate = p_fldate.
ENDLOOP.
‎2009 Oct 19 2:54 PM
OK - I ran a quick test. The results are mixed.
LOOP AT ... WHERE consistently ran in about 72% of the time as LOOP/CHECK. So it is faster.
The saving is about 0.3 msec for each hit.
Code:
REPORT ztest MESSAGE-ID 00.
DATA: start TYPE i,
end TYPE i,
dif TYPE i.
DATA: BEGIN OF itab OCCURS 0,
f1,
END OF itab.
DO 100000 TIMES.
itab-f1 = 'A'.
APPEND itab.
itab-f1 = 'B'.
APPEND itab.
itab-f1 = 'C'.
APPEND itab.
itab-f1 = 'D'.
APPEND itab.
itab-f1 = 'E'.
APPEND itab.
ENDDO.
DO 10 TIMES.
GET RUN TIME FIELD start.
LOOP AT itab WHERE f1 = 'C'.
ENDLOOP.
GET RUN TIME FIELD end.
dif = end - start.
WRITE: /001 'time for LOOP...WHERE :', dif, 'msec'.
GET RUN TIME FIELD start.
LOOP AT itab.
CHECK itab-f1 = 'C'.
ENDLOOP.
GET RUN TIME FIELD end.
dif = end - start.
WRITE: /001 'time for CHECK within LOOP:', dif, 'msec'.
ENDDO.