从内部表中提取唯一值



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

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

相关内容

  • 没有找到相关文章

最新更新