从内部表的一列或多列中提取唯一值的最有效方法是什么?
如果您有7.40 SP08或更高版本,您可以简单地使用内联语法来填充目标表(不需要LOOP GROUP BY):
DATA: it_unique TYPE STANDARD TABLE OF fieldtype.
it_unique = VALUE #(
FOR GROUPS value OF <line> IN it_itab
GROUP BY <line>-field WITHOUT MEMBERS ( value ) ).
这适用于任何类型的目标表。
对于旧版本使用:
DATA: it_unique TYPE HASHED TABLE OF fieldtype WITH UNIQUE KEY table_line.
LOOP AT it_itab ASSIGNING <line>.
INSERT <line>-field INTO TABLE lt_unique.
ENDLOOP.
上面的方法也适用于排序表。尽管我不建议将排序表用于此目的,除非您非常确定结果中只有几行。
忽略INSERT
的非零sy-subrc
。不需要进行两次键查找(一次用于存在检查,一次用于插入)。
如果目标必须是STANDARD TABLE,并且您有旧的ABAP堆栈,您可以选择使用
DATA: it_unique TYPE STANDARD TABLE OF fieldtype.
LOOP AT it_itab ASSIGNING <line>.
READ TABLE lt_unique WITH TABLE KEY table_line = <line>-field
TRANSPORTING NO FIELDS BINARY SEARCH.
INSERT <line>-field INTO lt_unique INDEX sy-tabix.
ENDLOOP.
这提供了与排序表相同的行为,但使用的是标准表。这是否比SORT/DELETE邻近重复项更有效取决于itab中重复条目的数量。重复条目越多,上述解决方案的速度就越快,因为它避免了对目标表进行不必要的追加。但另一方面,追加操作要比插入操作快。
在ABAP 7.40的SP08版本之前,从内部表或tab中提取唯一值的最有效方法如下:
LOOP AT lt_itab ASSIGNING <ls_itab>.
APPEND <ls_itab>-value TO lt_values.
ENDLOOP.
SORT lt_values.
DELETE ADJACENT DUPLICATES FROM lt_values.
在将给定的<ls_itab>-value
添加到内部表之前检查它的存在是另一种保证唯一性的方法,但是当插入到标准表时,可能会花费更多的计算成本。对于排序或散列的目标表,使用:
LOOP AT lt_itab ASSIGNING <ls_itab>.
READ TABLE lt_sorted_values WITH KEY table_line = <ls_itab>-value BINARY SEARCH.
IF sy-subrc <> 0.
APPEND <ls_itab>-value TO lt_sorted_values.
ENDIF.
ENDLOOP.
请注意,使用第一种方法,但将值插入到一个假表中,然后使用APPEND LINES OF lt_dummy INTO lt_sorted_values
,可能更快,但是中间表的大小可能会混淆。
然而,在ABAP 7.40支持包08中,
GROUP BY
循环提供了更好的方法来提取唯一值。顾名思义,这些函数类似于SQL的GROUP BY
。例如,下面的代码将从内部表中提取唯一的项目编号:
LOOP AT lt_project_data ASSIGNING FIELD-SYMBOL(<ls_grp_proj>)
GROUP BY ( project = <ls_grp_proj>-proj_number ) ASCENDING
WITHOUT MEMBERS
ASSIGNING FIELD-SYMBOL(<ls_grp_unique_proj>).
APPEND <ls_grp_unique_proj>-project TO lt_unique_projects.
ENDLOOP.
相同的逻辑可以扩展到检索唯一对,例如EKPO
表的组合主键,EBELN
("采购文档",po_nr
)和EBELP
("采购文档的项目编号",po_item
):
LOOP AT lt_purchasing_document_items ASSIGNING FIELD-SYMBOL(<ls_grp_po>)
GROUP BY ( number = <ls_grp_po>-po_nr
item = <ls_grp_po>-po_item ) ASCENDING
WITHOUT MEMBERS
ASSIGNING FIELD-SYMBOL(<ls_grp_po_item>).
APPEND VALUE #( ebeln = <ls_grp_po_item>-number
ebelp = <ls_grp_po_item>-item ) TO lt_unique_po_items.
ENDLOOP.
根据新ABAP 7.40版本的SAP设计者之一Horst Keller的说法,GROUP BY循环的性能可能与这些循环的手动实现相同。根据实现这种自定义循环的效率,它甚至可能更快。请注意,对于GROUP BY
循环不可用的系统,这些方法将比上面给出的两种方法更快。
请注意,在大多数情况下,查询数据库以返回DISTINCT
值将会快得多,和性能方面的做法将使任何使用内部表的ABAP代码脱颖而出,特别是HANA系统上的。
这个怎么样?
lt_unique[] = lt_itab[].
SORT lt_unique[] BY field1 field2 field3...
DELETE ADJACENT DUPLICATES FROM lt_values COMPARING field1 field2 field3...