Quantcast
Channel: SCN : All Content - All Communities
Viewing all articles
Browse latest Browse all 3523

"SELECT DISTINCT" for internal tables - contest opened!

$
0
0

"Cultural Appropriation" being the new SJW buzz word in America, I am doing in the public some "New ABAP syntax features appropriation" to get accustomed to them. I didn't find yet a really satisfyingly simple expression for the simple task

 

"Given an internal table, create an internal table containing all the distinct values that appear in a certain column"

 

So this really is something very simple, similar to a SELECT DISTINCT in SQL.

 

In a good programming language, a simple task must have a simple solution.

 

So let's try.

 

I select some arbitrary 100 rows from a database table VBAK (sales order headers) into a standard table of line type VBAK. Now I want to have a standard table of elementary line type ERNAM, containinig the distinct values for ERNAM that appear in my selection. (See my pastebin for the SELECT statement and the frame around the following code snippets).

 

Solution with COLLECT

 

Using the idiom COLLECT for standard tables (which is not encouraged by the documentation, but works fine), I get this readable solution:

 

form with_collect using it_vbak type vbak_tab                   changing ct_ernam type ernam_tab.
 clear ct_ernam.   loop at it_vbak assigning field-symbol(<ls_vbak>).     collect <ls_vbak>-ernam into ct_ernam.   endloop.
endform.

COLLECT uses an internal auxiliary hash table for achieving uniqueness.

 

Using an auxiliary hash table explicitly

 

The hash can be made explicit, then I have the following solution:

 

form with_explicit_aux_hash using it_vbak type vbak_tab                             changing ct_ernam type ernam_tab.   data: lt_ernam type hashed table of ernam with unique key table_line.   loop at it_vbak assigning field-symbol(<ls_vbak>).     insert <ls_vbak>-ernam into table lt_ernam.   endloop.   ct_ernam = lt_ernam.
endform.

Now for the new ABAP syntax idioms (not so new any more, by the way).

 

Using the VALUE operator

 

I found a solution with the VALUE operator:

 

form with_value_for using it_vbak type vbak_tab                     changing ct_ernam type ernam_tab.   ct_ernam = value #( for <ls_vbak> in it_vbak                       ( <ls_vbak>-ernam )  " Inserting into a hash table will dump on multiple values.                                            " No way to avoid this                      ).   sort ct_ernam.   delete adjacent duplicates from ct_ernam.
endform.

Which is readable, but it's not nice that the implicit insert of table line ( <ls_vbak>-ernam ) throws an exception if the target table has a unique key. This can't be trapped inside of the expression. So we can't use an auxiliary hash table, like in the last example. We have to collect all the ERNAM's firstly, and then have to delete the duplicates later on.

 

Not nice. But I didn't see a better way to do it with VALUE. Do you?

 

Using the REDUCE operator

 

Just for curiosity, I also tried the REDUCE operator. I found a combination of REDUCE and COND to give the desired result. But the final expression is far too complicated for such a simple task:

 

form with_reduce_for using it_vbak type vbak_tab                      changing ct_ernam type ernam_tab.   ct_ernam = reduce #( init names type ernam_tab                        for <ls_vbak> in it_vbak                        next names =                          cond #(                            when line_exists( names[ table_line = <ls_vbak>-ernam ] ) then names                            else value #( base names ( <ls_vbak>-ernam ) )                            )                        ).
endform.

Using the GROUP BY keyword

 

But even with the GROUP BY idiom, which seems to be tailored for situations like the given, the solution is too long for my taste:

 

form with_grouping using it_vbak type vbak_tab                    changing ct_ernam type ernam_tab.     clear ct_ernam.     loop at it_vbak assigning field-symbol(<ls_vbak>)                     group by <ls_vbak>-ernam                     ascending                     assigning field-symbol(<lv_group>).       append <lv_group> to ct_ernam.     endloop.
endform.

Other suggestions?

 

Find my complete example report ZZ_EXTRACT_SUBTABLE on pastebin

 

Maybe I am blind for quicker and better solutions! Any suggestions are welcome!


Viewing all articles
Browse latest Browse all 3523

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>