2

每个项目都应该有一个独特的 SecondNo + Drawing 组合。由于输入错误,一些组合出现了两次。

我需要使用 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

我该如何解决这个问题?我尝试了 2 种方法并失败了:

  1. 对数据进行排序并尝试在上一行的值等于下一个值时打印出每一个

  2. 计算重复项并显示所有重复项。

我在哪里设置条件?在循环区域?

我试过这个:

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.
4

4 回答 4

2

从 ABAP 7.40 开始,您可以使用GROUP BY带有GROUP SIZE单词的结构,以便仅考虑具有至少 2 个元素的组。

对于这两种结构,可以通过两种方式在分组的行处循环: * 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

您可能希望生成包含重复项的下表:

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

解决方案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

输出:

List of duplicates:

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

解决方案... 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.

注意:对于删除非重复项,而不是使用附加DELETE语句,可以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
于 2019-07-12T07:36:51.847 回答
1

只要您正确排列字段,您就可以使用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.
于 2014-10-03T07:03:21.890 回答
0

这是我的 2p 价值,您可以根据自己的需要减少一些,并且您还应该考虑正在处理的数据量。此方法仅适用于较小的集合。就我个人而言,我喜欢在源头上防止错误的记录。在输入过程中捕获错误。但是,如果您最终陷入困境,那么解决问题的方法肯定不止一种。

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.

于 2019-11-15T23:12:21.493 回答
0

我只需要根据两个字段报告错误的重复行,因此使用以下内容。

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.
于 2019-11-06T20:35:07.150 回答