如何通过内部表中给出的几个关键字段从db表元组中进行选择

时间:2015-04-15 07:01:55

标签: key abap composite opensql

我想在具有6个关键字段的数据库表上执行SELECT查询,假设它们是keyA,keyB,...,keyF。

作为我的ABAP功能模块的输入参数,我确实收到一个内部表,其中包含关键字段的结构,因此该内部表中的每个条目对应于数据库表中的一个元组。

因此,我只需要从数据库表中选择与我的内部表中的条目对应的所有元组。 此外,我想在完全相同的查询中聚合该数据库表中的amount列。

在伪SQL中,查询看起来如下: SELECT SUM(amount)FROM表WHERE(keyA,keyB,keyC,keyD,keyE,keyF)IN {internal table}。

但是,这种表示在ABAP OpenSQL中是不可能的。

只允许一个列(例如keyA)声明,而不是复合键。此外,我只能在关键字IN后使用“选择表”(带有SIGN,OPTIOn,LOW,HIGH的那些)。 使用FOR ALL ENTRIES似乎是可行的,但是在这种情况下我不能使用SUM,因为在同一个查询中不允许聚合。

有什么建议吗?

3 个答案:

答案 0 :(得分:3)

为了选择内部表的每个条目的记录,通常ABAP Open SQL中的for all entries成语是你的朋友。在您的情况下,您还需要汇总一笔金额。遗憾的是,不允许使用与for all entries一起使用的SELECT语句的结果集来使用聚合函数。在我看来,这种情况下的最佳方法是从ABAP层中的结果集计算总和。以下示例适用于我的系统(请注意:使用7.40附带的新ABAP语言功能,可以大大缩短整个代码。)

report  zz_ztmp_test.

start-of-selection.
  perform test.

* Database table ZTMP_TEST :
* ID     -  key field  - type CHAR10
* VALUE  -  no key field - type INT4
* Content: 'A' 10, 'B' 20, 'C' 30, 'D' 40, 'E' 50

types: ty_entries type standard table of ztmp_test.

* ---
form test.

  data: lv_sum    type i,
        lt_result type ty_entries,
        lt_keys   type ty_entries.

  perform fill_keys changing lt_keys.

  if lt_keys is not initial.
    select * into table lt_result
           from ztmp_test
           for all entries in lt_keys
           where id = lt_keys-id.
  endif.

  perform get_sum using lt_result
                  changing lv_sum.

  write: / lv_sum.

endform.

form fill_keys changing ct_keys type ty_entries.
  append :
    'A' to ct_keys,
    'C' to ct_keys,
    'E' to ct_keys.
endform.

form get_sum using it_entries type ty_entries
              changing value(ev_sum) type i.
  field-symbols: <ls_test> type ztmp_test.

  clear ev_sum.
  loop at it_entries assigning <ls_test>.
    add <ls_test>-value to ev_sum.
  endloop.

endform.

答案 1 :(得分:2)

我会使用FOR ALL ENTRIES来获取所有相关的行,然后LOOP围绕结果表并将相关字段添加到总计中。如果你有ABAP 740或更高版本,你可以使用REDUCE运算符来避免必须手动循环遍历表:

DATA(total) = REDUCE i( INIT sum = 0
                        FOR wa IN itab NEXT sum = sum + wa-field ).

答案 2 :(得分:0)

一种可能的方法是使用语句SELECT...ENDSELECT语句同时在SELECT循环内进行汇总。

计算工厂的所有订单行/数量的示例:

TYPES: BEGIN OF ls_collect,
       werks TYPE t001w-werks,
       menge TYPE ekpo-menge,
      END OF ls_collect.
DATA: lt_collect TYPE TABLE OF ls_collect.

SELECT werks UP TO 100 ROWS
  FROM t001w
  INTO TABLE @DATA(lt_werks).

SELECT werks, menge
  FROM ekpo
  INTO @DATA(order)
   FOR ALL ENTRIES IN @lt_werks
  WHERE werks = @lt_werks-werks.

  COLLECT order INTO lt_collect.
ENDSELECT.

该样本没有商业意义,仅出于教育目的而放置在此处。

从ABAP 751版本开始,CTE(公用表表达式)是另一种更健壮和现代的方法。此技术特别适用于总/小计任务:

WITH
  +plants AS (
    SELECT werks UP TO 100 ROWS
      FROM t011w ),
  +orders_by_plant AS (
     SELECT SUM( menge )
      FROM ekpo AS e
      INNER JOIN +plants AS m
         ON e~werks = m~werks 
      GROUP BY werks )

    SELECT werks, menge
       FROM +orders_by_plant
       INTO TABLE @DATA(lt_sums)
       ORDER BY werks.

cl_demo_output=>display( lt_sums ).

第一个表表达式+material是您的内部表,上述材料选择的第二个+orders_by_mat数量总计,最后一个查询是最终输出查询。