Finding duplicates in ABAP internal table via grouping

自闭症网瘾萝莉.ら 提交于 2019-12-04 20:24:19

Given

TYPES: BEGIN OF key_row_type,
         matnr TYPE matnr,
         werks TYPE werks_d,
       END OF key_row_type.
TYPES key_table_type TYPE
  STANDARD TABLE OF key_row_type
  WITH DEFAULT KEY.

TYPES: BEGIN OF group_row_type,
         matnr TYPE matnr,
         werks TYPE werks_d,
         size  TYPE i,
       END OF group_row_type.
TYPES group_table_type TYPE
  STANDARD TABLE OF group_row_type
  WITH DEFAULT KEY.

TYPES tt_materials TYPE STANDARD TABLE OF marc WITH DEFAULT KEY.
DATA(materials) = VALUE tt_materials(
  ( matnr = '23' werks = 'US' maabc = 'B' )
  ( matnr = '42' werks = 'DE' maabc = 'A' )
  ( matnr = '42' werks = 'DE' maabc = 'B' ) ).

When

DATA(duplicates) =
  VALUE key_table_type(
    FOR key IN VALUE group_table_type(
      FOR GROUPS group OF material IN materials
      GROUP BY ( matnr = material-matnr
                 werks = material-werks
                 size  = GROUP SIZE )
      WITHOUT MEMBERS ( group ) )
    WHERE ( size > 1 )
    ( matnr = key-matnr
      werks = key-werks ) ).

Then

cl_abap_unit_assert=>assert_equals(
    act = duplicates
    exp = VALUE tt_materials( ( matnr = '42' werks = 'DE') ) ).

Readability of this solution is so bad that you should only ever use it in a method with a revealing name like collect_duplicate_keys.

Also note that the statement's length increases with a growing number of key fields, as the GROUP SIZE addition requires listing the key fields one by one as a list of simple types.

So, I just put it as answer, as we with Florian weren't able to think out something better.
If somebody is able to improve it, just do it.

TYPES tt_materials TYPE STANDARD TABLE OF marc WITH DEFAULT KEY. 

DATA duplicates TYPE tt_materials. 
LOOP AT materials INTO DATA(material) 
GROUP BY ( id = material-matnr 
           status = material-pstat 
           size = GROUP SIZE ) 
ASCENDING REFERENCE INTO DATA(group_ref). 

CHECK group_ref->*-size > 1. 
duplicates = VALUE tt_materials( BASE duplicates FOR <status> IN GROUP group_ref ( <status> ) ). 

ENDLOOP.

What about the classics? I'm not sure if they are deprecated or so, but my first think is about to create a table clone, DELETE ADJACENT-DUPLICATES on it and then just compare both lines( )... I'll be eager to read new options.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!