无需循环即可获得总数

Get total without LOOP

我参考了这个问题和答案。但我的要求比这简单得多。我只需要类别及其相应的总数。

我有内部 table 喜欢:

Category Amount
AAA     10
AAA     20
BBB     30
CCC     40
CCC     50
CCC     60

我需要构建内部 table 如下:

Category Amount
AAA       30
BBB       30
CCC       150

有人可以帮忙吗?

从 7.40 版及更高版本开始,这可以通过在内部 tables 中组合分组来实现(FOR GROUPS) with REDUCE 用于计算每组的总和。

首先是几个声明:

TYPES:
   BEGIN OF data_struct,
    category TYPE c LENGTH 3,
    amount TYPE i,
   END OF data_struct,
   data_tab TYPE STANDARD TABLE OF data_struct WITH EMPTY KEY.

DATA(input) = VALUE data_tab(
    ( Category = 'AAA' Amount = 10 )
    ( Category = 'AAA' Amount = 20 )
    ( Category = 'BBB' Amount = 30 )
    ( Category = 'CCC' Amount = 40 )
    ( Category = 'CCC' Amount = 50 )
    ( Category = 'CCC' Amount = 60 )
).

这里是解决方案:

DATA(output) = VALUE data_tab(
    FOR GROUPS group OF input_line IN input 
        GROUP BY ( category = input_line-category )
        (   category = group-category
            amount = REDUCE #(
                INIT subtotal = 0
                FOR group_line IN GROUP group
                NEXT subtotal  = subtotal  + group_line-amount 
            ) 
        ) 
).

现在这里到底发生了什么?

内部 table output 的数据由 FOR GROUPS 生成。 FOR GROUPS table 表达式由三部分组成:组的声明、分组条件和结果。

首先关于声明部分:GROUPS group OF input_line IN input。这定义了有一个名为“组”的组,它的源是内部 table“输入”,我们将该源 table 的每一行称为“input_line”。

接下来是分组标准:GROUP BY ( category = input_line-category )。这意味着每个组都由具有单个字段“category”的键标识,并且我们希望对字段“category”相同的所有行进行分组。

现在是结果部分:

( category = group-category
  amount = REDUCE #(
    INIT subtotal = 0
    FOR group_line IN GROUP group
    NEXT subtotal = subtotal + group_line-amount
  )
)

这定义了每个组在输出集中应该如何表示。第一个字段“category”很简单 - 只需输入名为“group”的组的“category”值即可。

第二个字段“金额”有点复杂,因为它的值是由REDUCE计算的。 REDUCE 构造表达式的目的是取多个值并将它们变成一个值。它通过执行以下操作来做到这一点:

  1. 声明并初始化一个变量:INIT subtotal = 0
  2. 对内部 table 或外部 FOR GROUPS 中的一组行进行循环。在本例中是后者:FOR group_line IN GROUP group
  3. 对该输入的每一行执行相同的代码片段,更改变量。在这种情况下,将其金额添加到小计中:NEXT subtotal = subtotal + group_line-amount
  4. Return步骤1中声明的变量的最终值。

调试器的结果: