我可以将 FOR ALL ENTRIES 与 GROUP BY 一起使用吗?
Can I use FOR ALL ENTRIES with GROUP BY?
目前代码看起来像这样:
LOOP AT lt_orders ASSIGNING <fs_order>.
SELECT COUNT(*) AS cnt
FROM order_items
INTO <fs_order>-cnt
WHERE order_id = <fs_order>-order_id.
ENDLOOP.
这是报告中最慢的部分。我想加快速度。
如何将 FOR ALL ENTRIES 与 GROUP BY 一起使用?
Check the documentation. You can't use GROUP BY
. Maybe in this case, you could try selecting your items with FAE outside of the loop, then count them using a parallel cursor:
REPORT.
TYPES: BEGIN OF ty_result,
vbeln TYPE vbeln,
cnt TYPE i.
TYPES: END OF ty_result.
DATA: lt_headers TYPE SORTED TABLE OF ty_result WITH UNIQUE KEY vbeln,
lv_tabix TYPE sy-tabix VALUE 1.
"get the headers
SELECT vbeln FROM vbak UP TO 100 ROWS INTO CORRESPONDING FIELDS OF TABLE lt_headers.
"get corresponding items
SELECT vbeln, posnr FROM vbap FOR ALL ENTRIES IN @lt_headers
WHERE vbeln EQ @lt_headers-vbeln
ORDER BY vbeln, posnr
INTO TABLE @DATA(lt_items).
LOOP AT lt_headers ASSIGNING FIELD-SYMBOL(<h>).
LOOP AT lt_items FROM lv_tabix ASSIGNING FIELD-SYMBOL(<i>).
IF <i>-vbeln NE <h>-vbeln.
lv_tabix = sy-tabix.
EXIT.
ELSE.
<h>-cnt = <h>-cnt + 1.
ENDIF.
ENDLOOP.
ENDLOOP.
BREAK-POINT.
或者加入 header/item 并在项目 ID 上使用不同的计数(无论是在您的 table 中的哪一列)。
你应该可以做类似的事情
SELECT COUNT(order_item_id) AS cnt, order_id
FROM order_items
INTO CORRESPONDING FIELDS OF TABLE lt_count
GROUP BY order_id.
假设 order_item_id
是 order_items
table 中的一个键。并假设 lt_count
有两个字段:cnt
类型 int8
和 order_id
与其他 order_id
字段
类型相同
PS:然后您可以遍历 lt_count
并将计数移动到 lt_orders
。或者反过来。要加快循环速度,请对 table 之一进行排序并使用 READ ... BINARY SEARCH
我使用 table KNB1(公司代码中的客户主),我们有客户,这些客户是在多个公司代码中创建的。
请注意,由于 FOR ALL ENTRIES,您必须 SELECT 完整密钥。
TYPES: BEGIN OF ty_knb1,
kunnr TYPE knb1-kunnr,
count TYPE i,
END OF ty_knb1.
TYPES: BEGIN OF ty_knb1_fae,
kunnr TYPE knb1-kunnr,
END OF ty_knb1_fae.
DATA: lt_knb1_fae TYPE STANDARD TABLE OF ty_knb1_fae.
DATA: lt_knb1 TYPE HASHED TABLE OF ty_knb1
WITH UNIQUE KEY kunnr.
DATA: ls_knb1 TYPE ty_knb1.
DATA: ls_knb1_db TYPE knb1.
START-OF-SELECTION.
lt_knb1_fae = VALUE #( ( kunnr = ... ) ). "add at least one customer which is created in several company codes
ls_knb1-count = 1.
SELECT kunnr bukrs
INTO CORRESPONDING FIELDS OF ls_knb1_db
FROM knb1
FOR ALL ENTRIES IN lt_knb1_fae
WHERE kunnr EQ lt_knb1_fae-kunnr.
ls_knb1-kunnr = ls_knb1_db-kunnr.
COLLECT ls_knb1 INTO lt_knb1.
ENDSELECT.
我不认为你需要这么久的答案。
我也再次看到人们对您的问题投反对票 - 为什么?
因为你个人不喜欢?
然而,对于那些可能需要的人,答案是:
- 为您的 lt_orders 创建范围 table,例如 lt_orders_range。
- 使用“where order_id in lt_orders_range”执行select“order_id, count( * )”。
如果您认为创建范围 table 太多了,您将通过 运行 为所有订单仅使用一个 select 而不是单个 [=27] 来节省大量性能=] 对于每个订单 ID。
所以这绝对有道理
不直接,只能通过 CDS 查看
虽然所有答案都提供了比问题中的解决方案更快的解决方案,但并未提及最快的方法。
如果您至少有 Netweaver 7.4、EHP 5(您应该有,它于 2014 年发布),即使您没有使用 HANA,也可以使用 CDS 视图。
它仍然不能直接完成,因为 OpenSQL 不允许使用 GROUP BY 的 FOR ALL ENTRIES,并且 CDS 视图无法处理 FOR ALL ENTRIES。但是,您可以分别创建一个。
光盘:
@AbapCatalog.sqlViewName: 'zorder_i_fae'
DEFINE VIEW zorder_items_fae AS SELECT FROM order_items {
order_id,
count( * ) AS cnt,
}
GROUP BY order_id
OpenSQL:
SELECT *
FROM zorder_items_fae
INTO TABLE @DATA(lt_order_cnt)
FOR ALL ENTRIES IN @lt_orders
WHERE order_id = @lt_orders-order_id.
速度
如果 lt_orders
包含来自 table ORDER_ITEMS
的所有可能 order_id
值的大约 30% 以上,则 更快。 (显然使用更多内存)
但是,如果您只需要数百万中的几个 order_id
个值,则此解决方案比任何其他答案快大约 10 倍,比原始答案快 100 倍。
目前代码看起来像这样:
LOOP AT lt_orders ASSIGNING <fs_order>.
SELECT COUNT(*) AS cnt
FROM order_items
INTO <fs_order>-cnt
WHERE order_id = <fs_order>-order_id.
ENDLOOP.
这是报告中最慢的部分。我想加快速度。
如何将 FOR ALL ENTRIES 与 GROUP BY 一起使用?
Check the documentation. You can't use GROUP BY
. Maybe in this case, you could try selecting your items with FAE outside of the loop, then count them using a parallel cursor:
REPORT.
TYPES: BEGIN OF ty_result,
vbeln TYPE vbeln,
cnt TYPE i.
TYPES: END OF ty_result.
DATA: lt_headers TYPE SORTED TABLE OF ty_result WITH UNIQUE KEY vbeln,
lv_tabix TYPE sy-tabix VALUE 1.
"get the headers
SELECT vbeln FROM vbak UP TO 100 ROWS INTO CORRESPONDING FIELDS OF TABLE lt_headers.
"get corresponding items
SELECT vbeln, posnr FROM vbap FOR ALL ENTRIES IN @lt_headers
WHERE vbeln EQ @lt_headers-vbeln
ORDER BY vbeln, posnr
INTO TABLE @DATA(lt_items).
LOOP AT lt_headers ASSIGNING FIELD-SYMBOL(<h>).
LOOP AT lt_items FROM lv_tabix ASSIGNING FIELD-SYMBOL(<i>).
IF <i>-vbeln NE <h>-vbeln.
lv_tabix = sy-tabix.
EXIT.
ELSE.
<h>-cnt = <h>-cnt + 1.
ENDIF.
ENDLOOP.
ENDLOOP.
BREAK-POINT.
或者加入 header/item 并在项目 ID 上使用不同的计数(无论是在您的 table 中的哪一列)。
你应该可以做类似的事情
SELECT COUNT(order_item_id) AS cnt, order_id
FROM order_items
INTO CORRESPONDING FIELDS OF TABLE lt_count
GROUP BY order_id.
假设 order_item_id
是 order_items
table 中的一个键。并假设 lt_count
有两个字段:cnt
类型 int8
和 order_id
与其他 order_id
字段
PS:然后您可以遍历 lt_count
并将计数移动到 lt_orders
。或者反过来。要加快循环速度,请对 table 之一进行排序并使用 READ ... BINARY SEARCH
我使用 table KNB1(公司代码中的客户主),我们有客户,这些客户是在多个公司代码中创建的。
请注意,由于 FOR ALL ENTRIES,您必须 SELECT 完整密钥。
TYPES: BEGIN OF ty_knb1,
kunnr TYPE knb1-kunnr,
count TYPE i,
END OF ty_knb1.
TYPES: BEGIN OF ty_knb1_fae,
kunnr TYPE knb1-kunnr,
END OF ty_knb1_fae.
DATA: lt_knb1_fae TYPE STANDARD TABLE OF ty_knb1_fae.
DATA: lt_knb1 TYPE HASHED TABLE OF ty_knb1
WITH UNIQUE KEY kunnr.
DATA: ls_knb1 TYPE ty_knb1.
DATA: ls_knb1_db TYPE knb1.
START-OF-SELECTION.
lt_knb1_fae = VALUE #( ( kunnr = ... ) ). "add at least one customer which is created in several company codes
ls_knb1-count = 1.
SELECT kunnr bukrs
INTO CORRESPONDING FIELDS OF ls_knb1_db
FROM knb1
FOR ALL ENTRIES IN lt_knb1_fae
WHERE kunnr EQ lt_knb1_fae-kunnr.
ls_knb1-kunnr = ls_knb1_db-kunnr.
COLLECT ls_knb1 INTO lt_knb1.
ENDSELECT.
我不认为你需要这么久的答案。 我也再次看到人们对您的问题投反对票 - 为什么? 因为你个人不喜欢?
然而,对于那些可能需要的人,答案是:
- 为您的 lt_orders 创建范围 table,例如 lt_orders_range。
- 使用“where order_id in lt_orders_range”执行select“order_id, count( * )”。
如果您认为创建范围 table 太多了,您将通过 运行 为所有订单仅使用一个 select 而不是单个 [=27] 来节省大量性能=] 对于每个订单 ID。 所以这绝对有道理
不直接,只能通过 CDS 查看
虽然所有答案都提供了比问题中的解决方案更快的解决方案,但并未提及最快的方法。
如果您至少有 Netweaver 7.4、EHP 5(您应该有,它于 2014 年发布),即使您没有使用 HANA,也可以使用 CDS 视图。
它仍然不能直接完成,因为 OpenSQL 不允许使用 GROUP BY 的 FOR ALL ENTRIES,并且 CDS 视图无法处理 FOR ALL ENTRIES。但是,您可以分别创建一个。
光盘:
@AbapCatalog.sqlViewName: 'zorder_i_fae'
DEFINE VIEW zorder_items_fae AS SELECT FROM order_items {
order_id,
count( * ) AS cnt,
}
GROUP BY order_id
OpenSQL:
SELECT *
FROM zorder_items_fae
INTO TABLE @DATA(lt_order_cnt)
FOR ALL ENTRIES IN @lt_orders
WHERE order_id = @lt_orders-order_id.
速度
如果 lt_orders
包含来自 table ORDER_ITEMS
的所有可能 order_id
值的大约 30% 以上,则
但是,如果您只需要数百万中的几个 order_id
个值,则此解决方案比任何其他答案快大约 10 倍,比原始答案快 100 倍。