从内部表的一列或多列中提取唯一值的最有效方法是什么?
答案 0 :(得分:6)
在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.
请注意,使用第一种方法但将值插入虚拟表后跟APPEND LINES OF lt_dummy INTO lt_sorted_values
可能会更快,但中间表的大小可能会混淆。
从ABAP 7.40 Support Package 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
(&#34;采购文档&#34;,po_nr
)和EBELP
(&#34;采购文件的项目编号&#34;,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表示the performance of GROUP BY loops is likely to be the same作为这些LOOP的手动实现。根据如何(有效)实现这样的自定义循环,它甚至可能更快。请注意,对于GROUP BY
循环不可用的系统,这些方法将比上面给出的两种方法更快。
请注意,在大多数情况下,查询数据库以返回DISTINCT
值将会快得多并且在性能方面这样做会破坏任何使用内部表格的ABAP代码, HANA系统上的尤其。
答案 1 :(得分:6)
如果你有 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-subrc
的非零INSERT
被忽略。无需进行两次密钥查找(一次用于存在检查,一次用于插入)。
如果目标必须是 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 ADJACENT DUPLICATES更有效取决于itab中重复条目的数量。存在的重复条目越多,上述解决方案就越快,因为它避免了对目标表的不必要的附加。但另一方面,追加比插入更快。
答案 2 :(得分:3)
这个怎么样?
lt_unique[] = lt_itab[].
SORT lt_unique[] BY field1 field2 field3...
DELETE ADJACENT DUPLICATES FROM lt_values COMPARING field1 field2 field3...