Count itab rows that meet some condition?
Asked Answered
G

5

7

I get a internal table from a Function Module call that returns ~ 100 rows. About 40% of the rows are not relevant to me because I only need the entries with PAR1 = "XYZ". On SQL tables (transparent tables), I can use a

select count(*) from tab where PAR1 = "XYZ" 

to get the number of valid entries.

Looking at the documentation, all I could find was the READ Table syntax to iterate through the table. My current approach is to basically have a loop and increase if the row contains the value I want. But this seems very inefficient.

Is there a better approach for my requirement?

Gum answered 5/8, 2013 at 14:54 Comment(0)
W
9

Do whatever feels right to you. With ~100 rows, virtually nothing will make a huge difference in runtime. For me, stability would be more important than speed in this case.

That being said, you could try this:

LOOP AT lt_my_table TRANSPORTING NO FIELDS WHERE par1 = 'XYZ'.
  ADD 1 TO l_my_counter.
ENDLOOP.
Willianwillie answered 5/8, 2013 at 15:31 Comment(0)
S
13

As from 740 SP05 you can use:

DATA(lv_lines) = REDUCE i( INIT x = 0 FOR wa IN gt_itab
                    WHERE( F1 = 'XYZ' ) NEXT x = x + 1 ).

for counting the number of lines in gt_itab meeting codntion f1 = 'xyz'.

Standardbearer answered 11/8, 2017 at 12:34 Comment(7)
The only correct answer for modern programming. This can of course also be used in-line (IF REDUCE...) so you don't need to declare any variables. Though be careful: technically this declares both x and wa, though only once meaning that you can have multiple REDUCE expressions using the same result and work area variable names.Clotilde
Thank you for that great answer! Is it possible to put in multipe WHERE conditions to reduce results furthermore?Fimble
This worked for me - but only after adding a space between WHERE and (Hexagram
@Clotilde could you give an example how the code would look like without declaring any variables? I don't understand how it can work.Hexagram
@Hexagram Only if you're evaluating the result directly. Say if you want to run code X only if there are more than 5 lines you can do: IF REDUCE #( .... ) > 5. [X]. ENDIF. Any other approach to this problem requires declaring variables the regular way meaning they can't be used in-line.Clotilde
@Clotilde I think I gotcha - by "don't need to declare any variables" you just meant lv_lines in this case - right? Because I thought you found a way to also get rid of x and waHexagram
@Hexagram Ah yes, I just meant the lv_lines indeed. Sadly I don't think there's a way around needing to have those "temporary variables" declared.Clotilde
W
9

Do whatever feels right to you. With ~100 rows, virtually nothing will make a huge difference in runtime. For me, stability would be more important than speed in this case.

That being said, you could try this:

LOOP AT lt_my_table TRANSPORTING NO FIELDS WHERE par1 = 'XYZ'.
  ADD 1 TO l_my_counter.
ENDLOOP.
Willianwillie answered 5/8, 2013 at 15:31 Comment(0)
H
6

If the entries in the internal table are irrelevant you could do something like this.

DELETE lt_table WHERE par1 <> 'XYZ'.

Then you can count the remaining relevant records by using lines( lt_table ) or DESCRIBE TABLE lt_table LINES l_number_of_lines.

Here is an example.

TYPES: BEGIN OF tt_test,
  par1 TYPE c LENGTH 3,
  END OF tt_test.

DATA: lt_table TYPE TABLE OF tt_test.
DATA: l_number_of_lines TYPE i.
FIELD-SYMBOLS: <fs_par1> LIKE LINE OF lt_table.

APPEND INITIAL LINE TO lt_table ASSIGNING <fs_par1>.
<fs_par1>-par1 = 'XYZ'.
APPEND INITIAL LINE TO lt_table ASSIGNING <fs_par1>.
<fs_par1>-par1 = 'ABC'.
APPEND INITIAL LINE TO lt_table ASSIGNING <fs_par1>.
<fs_par1>-par1 = 'XYY'.
APPEND INITIAL LINE TO lt_table ASSIGNING <fs_par1>.
<fs_par1>-par1 = 'XYZ'.
APPEND INITIAL LINE TO lt_table ASSIGNING <fs_par1>.
<fs_par1>-par1 = 'XYZ'.

l_number_of_lines = LINES( lt_table ).
WRITE / l_number_of_lines.
DESCRIBE TABLE lt_table LINES l_number_of_lines.
WRITE / l_number_of_lines.
DELETE lt_table WHERE par1 <> 'XYZ'.
l_number_of_lines = LINES( lt_table ).
WRITE / l_number_of_lines.
Hienhieracosphinx answered 5/8, 2013 at 15:14 Comment(0)
G
2

Variant with FOR should also work, however it requires declared table type of that table:

TYPES: tt_mara TYPE TABLE OF mara WITH EMPTY KEY.
DATA(count) = lines( VALUE tt_mara( FOR line IN lt_mara WHERE ( matnr = 'XXX' ) ( line ) ) ).
Goya answered 21/10, 2020 at 15:27 Comment(0)
P
0

When I use this code Line DATA(count) = lines( VALUE tt_mara( FOR line IN lt_mara WHERE ( matnr = 'XXX' ) ( line ) ) ). I get the error "No component exists with the name "FOR". "FOR"."

Plural answered 26/9 at 17:15 Comment(1)
If you have a new question, please ask it by clicking the Ask Question button. Include a link to this question if it helps provide context. - From ReviewPupiparous

© 2022 - 2024 — McMap. All rights reserved.