【发布时间】:2015-12-28 01:25:27
【问题描述】:
从内部表的一列或多列中提取唯一值的最有效方法是什么?
【问题讨论】:
标签: abap internal-tables
从内部表的一列或多列中提取唯一值的最有效方法是什么?
【问题讨论】:
标签: abap internal-tables
如果您有 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 ADJACENT DUPLICATES 更有效取决于 itab 中重复条目的数量。存在的重复条目越多,上述解决方案就越快,因为它避免了对目标表的不必要附加。但另一方面,追加比插入快。
【讨论】:
在 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("采购单据",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 所说,the performance of GROUP BY loops is likely to be the same 是这些 LOOP 的手动实现。根据实现这种自定义循环的(无效)效率,它甚至可能更快。请注意,对于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...
【讨论】: