简体   繁体   English

在内部表中显示重复项

[英]Show duplicates in internal table

Each an every item should have an uniquie SecondNo + Drawing combination.每个项目都应该有一个唯一的 SecondNo + Drawing 组合。 Due to misentries, some combinations are there two times.由于错误,某些组合出现了两次。

I need to create a report with ABAP which identifies those combinations and does not reflect the others.我需要使用 ABAP 创建一个报告,该报告标识这些组合并且不反映其他组合。

Item:  SecNo: Drawing:
121       904      5000         double
122       904      5000         double
123       816      5100
124       813      5200
125       812      4900          double
126       812      4900          double
127       814      5300

How can I solve this?我该如何解决这个问题? I tried 2 approaches and failed:我尝试了两种方法并失败了:

  1. Sorting the data and tried to print out each one when the value of the upper row is equal to the next value对数据进行排序并尝试在上一行的值等于下一个值时打印出每一个

  2. counting the duplicates and showing all of them which are more then one.计算重复项并显示所有这些都不止一个。

Where do I put in the condition?我在哪里放置条件? in the loop area?在循环区?

I tried this:我试过这个:

REPORT  duplicates.

DATA: BEGIN OF lt_duplicates OCCURS 0,
        f2(10),
        f3(10),
      END OF lt_duplicates,
      it_test TYPE TABLE OF ztest WITH HEADER LINE,
      i       TYPE i.

SELECT DISTINCT f2 f3 FROM ztest INTO TABLE lt_duplicates.

LOOP AT lt_duplicates.

  IF f2 = lt_duplicates-f2 AND f3 = lt_duplicates-f3.
  ENDIF.

  i = LINES( it_test ).

  IF i > 1.
    LOOP AT it_test.
      WRITE :/ it_test-f1,it_test-f2,it_test-f3.
    ENDLOOP.
  ENDIF.

ENDLOOP.

You can use AT...ENDAT for this, provided that you arrange the fields correctly:您可以为此使用AT...ENDAT ,前提是您正确排列字段:

TYPES: BEGIN OF t_my_line,
         secno   TYPE foo,
         drawing TYPE bar,
         item    TYPE baz, " this field has to appear AFTER the other ones in the table
       END OF t_my_line.

DATA: lt_my_table TYPE TABLE OF t_my_line,
      lt_duplicates TYPE TABLE OF t_my_line.

FIELD-SYMBOLS: <ls_line> TYPE t_my_line.

START-OF-WHATEVER.

* ... fill the table ...

  SORT lt_my_table BY secno drawing.
  LOOP AT lt_my_table ASSIGNING <ls_line>.
    AT NEW drawing. " whenever drawing or any field left of it changes...
      FREE lt_duplicates.
    ENDAT.
    APPEND <ls_line> TO lt_duplicates.
    AT END OF drawing.
      IF lines( lt_duplicates ) > 1.
*       congrats, here are your duplicates...
      ENDIF.
    ENDAT.
  ENDLOOP.

From ABAP 7.40, you may use the GROUP BY constructs with the GROUP SIZE words so that to take into account only the groups with at least 2 elements.从 ABAP 7.40 开始,您可以将GROUP BY构造与GROUP SIZE字一起使用,以便仅考虑至少具有 2 个元素的组。

For both constructs, it's possible to loop at the grouped lines in two ways: * LOOP AT GROUP ... * ... FOR ... IN GROUP ...对于这两种结构,可以通过两种方式在分组的行上循环: * LOOP AT GROUP ... * ... FOR ... IN GROUP ...

Line#  Item    SecNo   Drawing
  1    121       904      5000         double
  2    122       904      5000         double
  3    123       816      5100
  4    124       813      5200
  5    125       812      4900         double
  6    126       812      4900         double
  7    127       814      5300

You might want to produce the following table containing the duplicates:您可能希望生成包含重复项的下表:

SecNo   Drawing   Lines
904      5000     [1,2]
812      4900     [5,6]

Solution with LOOP AT ... GROUP BY ... : LOOP AT ... GROUP BY ...解决方案

TYPES: BEGIN OF t_line,
         item    TYPE i,
         secno   TYPE i,
         drawing TYPE i,
       END OF t_line,
       BEGIN OF t_duplicate,
         secno   TYPE i,
         drawing TYPE i,
         num_dup TYPE i, " number of duplicates
         lines   TYPE STANDARD TABLE OF REF TO t_line WITH EMPTY KEY,
       END OF t_duplicate,
       t_lines      TYPE STANDARD TABLE OF t_line WITH EMPTY KEY,
       t_duplicates TYPE STANDARD TABLE OF t_duplicate WITH EMPTY KEY.

DATA(table) = VALUE t_lines(
    ( item = 121 secno = 904 drawing = 5000 )
    ( item = 122 secno = 904 drawing = 5000 )
    ( item = 123 secno = 816 drawing = 5100 )
    ( item = 124 secno = 813 drawing = 5200 )
    ( item = 125 secno = 812 drawing = 4900 )
    ( item = 126 secno = 812 drawing = 4900 )
    ( item = 127 secno = 814 drawing = 5300 ) ).

DATA(expected_duplicates) = VALUE t_duplicates(
    ( secno = 904 drawing = 5000 num_dup = 2 lines = VALUE #( ( REF #( table[ 1 ] ) ) ( REF #( table[ 2 ] ) ) ) )
    ( secno = 812 drawing = 4900 num_dup = 2 lines = VALUE #( ( REF #( table[ 5 ] ) ) ( REF #( table[ 6 ] ) ) ) ) ).

DATA(actual_duplicates) = VALUE t_duplicates( ).
LOOP AT table
    ASSIGNING FIELD-SYMBOL(<line>)
    GROUP BY
    ( secno   = <line>-secno
      drawing = <line>-drawing
      gs      = GROUP SIZE )
    ASSIGNING FIELD-SYMBOL(<group_table>).

  IF <group_table>-gs >= 2.
    actual_duplicates = VALUE #( BASE actual_duplicates
        ( secno   = <group_table>-secno
          drawing = <group_table>-drawing
          num_dup = <group_table>-gs
          lines   = VALUE #( FOR <line2> IN GROUP <group_table> ( REF #( <line2> ) ) ) ) ).
  ENDIF.

ENDLOOP.

WRITE : / 'List of duplicates:'.
SKIP 1.
WRITE : / 'Secno       Drawing     List of concerned items'.
WRITE : / '----------  ----------  ---------------------------------- ...'.
LOOP AT actual_duplicates ASSIGNING FIELD-SYMBOL(<duplicate>).
  WRITE : / <duplicate>-secno, <duplicate>-drawing NO-GROUPING.
  LOOP AT <duplicate>-lines INTO DATA(line).
    WRITE line->*-item.
  ENDLOOP.
ENDLOOP.

ASSERT actual_duplicates = expected_duplicates. " short dump if not equal

Output:输出:

List of duplicates:

Secno       Drawing     List of concerned items
----------  ----------  ---------------------------------- ...
       904        5000         121         122
       812        4900         125         126

Solution with ... VALUE type|#( FOR GROUPS ... GROUP BY ... :解决方案... VALUE type|#( FOR GROUPS ... GROUP BY ...

DATA(actual_duplicates) = VALUE t_duplicates(
    FOR GROUPS <group_table> OF <line> IN table
    GROUP BY
    ( secno   = <line>-secno
      drawing = <line>-drawing
      gs      = GROUP SIZE )
    ( secno   = <group_table>-secno
      drawing = <group_table>-drawing
      num_dup = <group_table>-gs
      lines   = VALUE #( FOR <line2> IN GROUP <group_table> ( REF #( <line2> ) ) ) ) ).
DELETE actual_duplicates WHERE num_dup = 1.

Note: for deleting non-duplicates, instead of using an additional DELETE statement, it can be done inside the VALUE construct by adding a LINES OF COND construct which adds 1 line if group size >= 2, or none otherwise (if group size = 1):注意:为了删除非重复项,而不是使用额外的DELETE语句,可以通过添加LINES OF COND构造在VALUE构造中完成LINES OF COND如果组大小 >= 2,则添加 1 行,否则不添加(如果组大小 = 1):

      ...
      gs      = GROUP SIZE )
    ( LINES OF COND #( WHEN <group_table>-gs >= 2 THEN VALUE #( "<== new line
    ( secno   = <group_table>-secno
      ...
      ... REF #( <line2> ) ) ) ) ) ) ) ). "<== 3 extra right parentheses

I needed simply to report duplicate lines in error based on two fields so used the following.我只需要根据两个字段报告错误的重复行,因此使用了以下内容。

LOOP AT gt_data INTO DATA(gs_data)

GROUP BY ( columnA = gs_data-columnA columnB = gs_data-columnB
size = GROUP SIZE index = GROUP INDEX ) ASCENDING
REFERENCE INTO DATA(group_ref).

IF group_ref->size > 1.
  PERFORM insert_error USING group_ref->columnA group_ref->columnB.
ENDIF.

ENDLOOP.

Here is my 2p worth, you could cut some out of this depending on what you want to do, and you should consider the amount of data being processed too.这是我的 2p 价值,您可以根据自己的需要从中减少一些,并且您还应该考虑正在处理的数据量。 This method is only really for smaller sets.这种方法只适用于较小的集合。 Personally I like to prevent erroneous records at the source.我个人喜欢从源头上防止错误记录。 Catching an error during input.在输入过程中捕获错误。 But if you do end up in a pickle there is definitely more than one way to solve the issue.但是,如果您最终陷入了泡菜中,那么解决问题的方法肯定不止一种。

TYPES: BEGIN OF ty_itab,
         item    TYPE i,
         secno   TYPE i,
         drawing TYPE i,
       END OF ty_itab.
TYPES: itab_tt TYPE STANDARD TABLE OF ty_itab.

DATA: lt_itab  TYPE itab_tt,
      lt_itab2 TYPE itab_tt,
      lt_itab3 TYPE itab_tt.

lt_itab = VALUE #(
                  ( item = '121' secno = '904' drawing = '5000' )
                  ( item = '122' secno = '904' drawing = '5000' )
                  ( item = '123' secno = '816' drawing = '5100' )
                  ( item = '124' secno = '813' drawing = '5200' )
                  ( item = '125' secno = '812' drawing = '4900' )
                  ( item = '126' secno = '812' drawing = '4900' )
                  ( item = '127' secno = '814' drawing = '5300' )
                ).

APPEND LINES OF lt_itab TO lt_itab2.
APPEND LINES OF lt_itab TO lt_itab3.

SORT lt_itab2 BY secno drawing.
DELETE ADJACENT DUPLICATES FROM lt_itab2 COMPARING secno drawing.   

* Loop at what is hopefully the smaller itab.
LOOP AT lt_itab2 ASSIGNING FIELD-SYMBOL(<line>).
  DELETE TABLE lt_itab3 FROM <line>.
ENDLOOP.

* itab1 has all originals.
* itab2 has the unique.
* itab3 has the duplicates.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM