我可以将 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_idorder_items table 中的一个键。并假设 lt_count 有两个字段:cnt 类型 int8order_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.

我不认为你需要这么久的答案。 我也再次看到人们对您的问题投反对票 - 为什么? 因为你个人不喜欢?

然而,对于那些可能需要的人,答案是:

  1. 为您的 lt_orders 创建范围 table,例如 lt_orders_range。
  2. 使用“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 倍。