5

从内部表的一列或多列中提取唯一值的最有效方法是什么?

4

3 回答 3

11

如果您有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.

以上也适用于排序表。尽管我不建议为此目的使用排序表,除非您确实确定结果中只有几行。

的非零sy-subrcINSERT被简单地忽略。无需进行两次密钥查找(一次用于存在检查,一次用于插入)。


如果目标必须是标准表并且您有旧的 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 ADJACENT DUPLICATES 更有效取决于 itab 中重复条目的数量。存在的重复条目越多,上述解决方案就越快,因为它避免了对目标表的不必要附加。但另一方面,追加比插入快。

于 2017-11-01T14:25:05.253 回答
9

在 ABAP 7.40 的 SP08 版本之前,从内部表或 itab 中提取唯一值的最有效方法如下:

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.

请注意,使用第一种方法但将值插入到虚拟表中后跟 anAPPEND LINES OF lt_dummy INTO lt_sorted_values 可能更快,但中间表的大小可能会混淆。


然而,ABAP 7.40 Support Package 08开始,循环提供了一种更好的方法来提取唯一值。顾名思义,这些功能类似于 SQL 的. 例如,以下代码将从内部表中提取唯一的项目编号:GROUP BYGROUP 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("Purchasing Document", po_nr) 和EBELP("Item Number of Purchasing Document", 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 循环的性能很可能与这些 LOOP 的手动实现相同。根据实现这种自定义循环的(无效)效率,它甚至可能更快。GROUP BY请注意,对于循环不可用的系统,这些方法将比上面给出的两种方法更快。


请注意,在大多数情况下,查询数据库以返回DISTINCT值会更快,并且在性能方面这样做会破坏任何使用内部表的 ABAP 代码,尤其是在 HANA 系统上。

于 2015-09-30T09:52:01.397 回答
3

这个怎么样?

lt_unique[] = lt_itab[].
SORT lt_unique[] BY field1 field2 field3...
DELETE ADJACENT DUPLICATES FROM lt_values COMPARING field1 field2 field3...
于 2015-10-01T02:43:38.073 回答