6

I need to find the sy-tabix of a the last entry in an internal table that matches v_key = x. I'm trying to do it with:

read table i_tab with key v_key = x

But since there are multiple entries in the table that match v_key = x, how can I make sure I get the sy-tabix of the last matching entry? I can't search by another key unfortunately.

Sandra Rossi
  • 11,934
  • 5
  • 22
  • 48
Suimon
  • 271
  • 1
  • 6
  • 15
  • Two possibilities: Either use LOOP AT ... WHERE v_key = x, SY-TABIX inside the loop at the last iteration will give you the line number. Or calculate the next possible value of x at byte level (byte+1), sort your table (with preference to a table with a sorted key), do a READ TABLE with "X+1", which will return SY-TABIX of the next line, so just subtract 1. – Sandra Rossi Jan 11 '19 at 10:50

5 Answers5

7

READ TABLE is for reading single lines, for more lines you have to use LOOP:

LOOP AT itab
     ASSIGNING ...
     WHERE vkey EQ x.
ENDLOOP.

Right after the LOOP sy-tabix will contain the last line, where the condition is true.

As it was pointed (see discussion below), for the best performance there has to exist a NON-UNIQUE SORTED key (either primary or secondary) for this field

József Szikszai
  • 4,791
  • 3
  • 14
  • 24
  • That works, but seems to get quite slow depending on the size of the table. Isn't there a faster method? – Suimon Jan 11 '19 at 12:10
  • @suimon, cf my comment, 2nd possibility. – Sandra Rossi Jan 11 '19 at 12:23
  • @SandraRossi I don' even have an idea what that is or how it works :/ But thanks, I'll google! – Suimon Jan 11 '19 at 12:26
  • @suimon cf comment converted into an answer with addendum to provide more details – Sandra Rossi Jan 11 '19 at 12:35
  • 3
    of course, with LOOP AT, `itab` must be a table declared `TYPE SORTED TABLE OF ... WITH NON-UNIQUE KEY v_key` for an optimum performance. Moreover, if you have many lines with the same v_key value, then the performance is not optimum (cf my answer for a better approach) – Sandra Rossi Jan 11 '19 at 12:37
  • @JozsefSzikszai maybe it's worth adding a remark about performance directly inside your answer. – Sandra Rossi Jan 12 '19 at 08:51
2

Another possibility, which is useful if you have many lines with the same v_key value.

First, make sure a line exists for X. If it's not found, then no need to pursue.

Calculate the next possible value (variable x_next_value) of the searched value (variable X). Examples:

  • If X is an integer, simply search X + 1. Example: for value 5, x_next_value will be 6.
  • If X are characters (C or string), then get the number of the last character (cl_abap_conv_**out**_ce=>uccpi), add 1, and update the last character (cl_abap_conv_**in**_ce=>uccpi).
  • Same kind of logic for other types of X.

Make sure your table is sorted (with preference to a table declared sorted table of ... with non-unique key v_key)

Then do READ TABLE itab WITH KEY v_key = x_next_value.

Important : even if no line is found, SY-TABIX will be set to the number of next line after all the lines having v_key = x (cf ABAP documentation of READ TABLE - Possible values for SY-SUBRC and SY-TABIX)

Pseudo code :

READ TABLE ... WITH KEY v_key = x_next_value.
" eventually BINARY SEARCH if itab is STANDARD instead of SORTED

CASE sy-subrc.
  WHEN 0.
    last_tabix_of_x = sy-tabix.
  WHEN 4.
    last_tabix_of_x = sy-tabix - 1.
  WHEN 8.
    last_tabix_of_x = lines( itab ).
ENDCASE.

Note : exactly two READ TABLE are needed to find the last matching result.

Sandra Rossi
  • 11,934
  • 5
  • 22
  • 48
  • it's not work if the key is not a sequence, if the table have keys (1,3, 8, 10) simple add 1 to key will fail. – I.B.N. Jan 11 '19 at 19:06
  • 2
    @I.B.N. In your example, searching for "9" will make `READ TABLE` "fail" with `SY-SUBRC` = 4 but at the same time `SY-TABIX` is set to 4 (point at line "10"), because it's the line with a value just above "9" - cf [ABAP documentation of READ TABLE - Possible values for SY-SUBRC and SY-TABIX](https://help.sap.com/http.svc/rc/abapdocu_753_index_htm/7.53/en-US/index.htm?file=abapread_table.htm) – Sandra Rossi Jan 11 '19 at 19:46
1

I think fastest way is

Sort itab by key.
read table itab with key key = v_key
                binary search.
loop at itab assign <fs> from sy-tabix.
   if <fs>-key ne v_key.
      exit.
   endif.
endloop.
I.B.N.
  • 992
  • 4
  • 15
  • 3
    Why not using a sorted index (primary or secondary key) so that your code has the same performance, but is smaller (same as code shown by @JozsefSzikszai) – Sandra Rossi Jan 12 '19 at 08:50
0

I am writing a different solution which might be helpful to you.

add one column keyno in table i_tab.

When you are inserting records in table i_tab, and there are multiple records to append in table i_tab for same key, you can add keyno for each records where same key has multiple records.

For Example:

Insertion of records in Table i_tab

i_tab_line-key = 'X'.
i_tab_line-keyno = 1.
APPEND i_tab_line to i_tab.
i_tab_line-key = 'X'.
i_tab_line-keyno = 2.
APPEND i_tab_line to i_tab.
i_tab_line-key = 'X'.
i_tab_line-keyno = 3.
APPEND i_tab_line to i_tab.

Table i_tab Sorting by Key Keyno descending.

   SORT i_tab by key keyno Desc.

Now Read Table will find last matching entry from table i_tab for the key.

   read table i_tab with key = X

regards,

Umar Abdullah

Umar Abdullah
  • 1,282
  • 1
  • 19
  • 37
-1
sort i_tab by v_key .
read table i_tab with key v_key = x binary search.

while i_tab-key = x
  lv_tabix = sy-tabix + 1 .
  read table i_tab index = lv_tabix .
endwhile.

result = lv_tabix -1 .
kuzey
  • 1
  • 3
  • you are right, it is not slow. Add a `sort i_tab`, and it will even give the right result. It will work identical to @I.B.N.'s answer, just a bit more awkward. – András Jan 13 '19 at 20:06
  • @I.B.N. solution is O(n) for the loop part. It needs a secondary key to be O(log n ). However, this solution is O(1) by default, no need to define a secondary key. It is far better. – kuzey Jan 14 '19 at 07:26
  • 1
    `READ TABLE i_tab` is indeed O(1), but you call it in a `WHILE`, making it O(n). It is _identical_ to the solution of @I.B.N, just not as readable. – András Jan 14 '19 at 09:26
  • @András you see Index used in the "read table" lines. It is O(1). period. – kuzey Jan 14 '19 at 12:26
  • it is o(1) _per executions_. You do more than one, if all `key` fields equal `x`, you do `n`. Exactly as I.B.N... – András Jan 14 '19 at 14:01