4
votes

As stated in the topic, I want to have a conditioned subset of an internal table inside another internal table.

Let us first look, what it may look like the old fashioned way.

DATA: lt_hugeresult TYPE tty_mytype,
      lt_reducedresult TYPE tty_mytype.  

SELECT "whatever" FROM "wherever" 
        INTO CORRESPONDING FIELDS OF TABLE lt_hugeresult 
          WHERE "any_wherecondition".
IF sy-subrc = 0.
  lt_reducedresult[] = lt_hugeresult[].
  DELETE lt_reducedresult WHERE col1 EQ 'a value'
                            AND col2 NE 'another value'
                            AND col3 EQ 'third value'.
 .
 .
 .


ENDIF.

We all may know this.

Now I was reading about the table reducing stuff, which is introduced with abap 7.40, appearently SP8.

Table Comprehensions – Building Tables Functionally

Table-driven:

VALUE tabletype( FOR line IN tab WHERE ( … )

( … line-… … line-… … ) )

For each selected line in the source table(s), construct a line in the result table. Generalization of value constructor from static to dynamic number of lines.

I was experimenting with that, but the results seem not really to fit, perhaps I am doing it wrong, or I might even need the condition-driven approach.

So, how would it look like, if I want to write the above statement with table comprehension techniques ?

Until now I have this, delivering not that, what I need, and I have seen, that it seems, as if the "not equal" is not possible...

DATA(reduced) =  VALUE tty_mytype( FOR checkline IN lt_hugeresult
                                   WHERE ( col1 = 'a value' )
                                         ( col2 = 'another value' )
                                         ( col3 = space )
                                 ).

Anyone having some hints ?

EDIT: Seems still not to work. Here is, as I do it:

Executable line:

enter image description here

Debugger results:

enter image description here

Wrong Reduced:

enter image description here

And what now ???

3
How do you fill in tbapi2045d4 table? Its content seems awkward to me. Give more common example (with MARA or BSEG) as BAPI2045D4 structure is used only in couple of QM BAPIs (in single parameters) and behavior of these parameters is not well documented.Suncatcher
You are absolutely right, there are not much worse documentations than in qm. The table is filled by a BAPI called BAPI_INSPOPER_GETRESULTS. But as You see in the debugger, those 5 entries are collected correctly. Only the reducing seems to fail, and this eben not always. This thing, which is black is just our namespace, because I created a tabletype with this structure as line-type. Might this cause any problems ?icbytes
The above syntax works perfectly for MARA.Suncatcher

3 Answers

3
votes

You could use the FILTER operator with the EXCEPT WHERE addition to filter out any rows that match the where clause:

lt_reducedresult = FILTER # ( lt_hugeresult EXCEPT WHERE col1 = 'a value' 
                                                     AND col2 <> 'another value' 
                                                     AND col3 = 'a third value' ).

Note that lt_hugeresult would have to be a sorted table, and the col1/col2/col3 need to be key components (you can specify a secondary key using the USING KEY addition).

The documentation for FILTER explicitly notes that:

Table filtering can also be performed using a table comprehension or a table reduction with an iteration expression for table iterations with FOR. The operator FILTER provides a shortened format for this special case and is more efficient to execute.

A table filter constructs the result row by row. If the result contains almost all rows in the source table, this method can be slower than copying the source table and deleting the surplus rows from the target table.

So your approach of using DELETE might actually be appropriate depending on the size of the table.

2
votes

The Table Iterations may be a lot confusing when you use WHERE, because of parenthesis groups.

The "NOT EQUAL" condition is very well supported, as I show below in the solution of your first example. The issue you observe is due to misproper use of parenthesis groups.

You must absolutely define the whole logical expression after WHERE Inside ONE parenthesis group (one, or several elementary conditions separated by logical operators AND, OR, etc.)

After the parenthesis group for WHERE, you define usually only one parenthesis group which corresponds to the line to be added to the target internal table. You may define subsequent parenthesis groups, if for each line in the source internal table, you want to add several lines in the target internal table.

In your example, only the first parenthesis group applies to WHERE (either col1 = 'a value' in your first example, or insplot = _ilnum in your second example).

The subsequent parenthesis groups correspond to the lines to be added, i.e. 2 lines are added for each source line in the first example (one line with col2 = 'another value', and one line with col3 = space), and 3 lines are added for each source line in the second example (one line with inspoper = i_evaluation-inspoper, one line with inspchar = i_evaluation-inspchar, one line corresponding to the line of _single_results).

So, you should write your code as follows.

First example :

DATA(reduced) =  VALUE tty_mytype( FOR checkline IN lt_hugeresult
                                   WHERE (     col1 =  'a value' 
                                           AND col2 <> 'another value'
                                           AND col3 =  'third value'
                                         )
                                   ( checkline )
                                 ).

Second example :

DATA(singres) = VALUE tbapi2045d4( FOR checkline IN _single_results
                                   WHERE (     insplot = _ilnum
                                           AND inspoper = i_evaluation-inspoper
                                           AND inspchar = i_evaluation-inspchar 
                                         )
                                   ( checkline )
                                 ).
1
votes

I compared old-fashioned syntax of your above example with table comprehension technique and got exactly the same result.
Actually, your sample is not functional because it lacks row specification for constructed table reduced. Try this one, which worked for me.

DATA(reduced) =  VALUE tty_mytype( FOR checkline IN lt_hugeresult
                                WHERE ( col1 = 'a value' AND 
                                        col2 = 'another value' AND
                                        col3 = space )
                                   ( checkline )
                                 ).

In the above sample we have the most basic type of result row specification where is is absolutely similar to source table. More sophisticated examples, where new table rows are evaluated with table iterations, can be found here.