使用表推导式对 itab 进行分组 + 聚合 [英] Grouping + aggregation of itab with table comprehensions
问题描述
相当典型的任务,但我坚持以漂亮的方式完成它.
Rather typical task but I'm stuck on doing it in a beautiful way.
例如,我需要找到每个供应商的最后一次发货,即找到每个供应商的最大日期的交货
For example, I need to find the last shipment for each vendor, i.e. to find delivery with the max date for the each vendor
VENDOR DELIVERY DATE
10 00055 01/01/2019
20 00070 01/19/2019
20 00088 01/20/2019
20 00120 11/22/2019
40 00150 04/01/2019
40 00200 04/10/2019
要填充的结果表
VENDOR DELIVERY DATE
10 00055 01/01/2019
20 00120 11/22/2019
40 00200 04/10/2019
我通过以下方式实现了这个,通过 DESCENDING,我觉得这很丑
I implemented this in a following way, via DESCENDING, which I find very ugly
LOOP AT itab ASSIGNING <wa> GROUP BY ( ven_no = <wa>-ven_no ) REFERENCE INTO DATA(vendor).
LOOP AT GROUP vendor ASSIGNING <ven> GROUP BY ( date = <vendor>-date ) DESCENDING.
CHECK NOT line_exists( it_vend_max[ ven_no = <ven>-ven_no ] ).
it_vend_max = VALUE #( BASE it_vend_max ( <ven> ) ).
ENDLOOP.
ENDLOOP.
有没有更优雅的方法来做到这一点?
Is there more elegant way to do this?
我也试过REDUCE
result = REDUCE #( vend_line = value ty_s_vend()
MEMBERS = VALUE ty_t_vend( )
FOR GROUPS <group_key> OF <wa> IN itab
GROUP BY ( key = <wa>-ven_no count = GROUP SIZE
ASCENDING
NEXT vend_line = VALUE #(
ven_no = <wa>-ven_no
date = REDUCE i( INIT max = 0
FOR m IN GROUP <group_key>
NEXT max = nmax( val1 = m-date
val2 = <wa>-date ) )
deliv_no = <wa>-deliv_no
MEMBERS = VALUE ty_s_vend( FOR m IN GROUP <group_key> ( m ) ) ).
但是REDUCE
从整个表中选择最大日期并且它只选择扁平结构,这不是我想要的.但是,在 ABAP 示例中,我看到了也可以进行表到表缩减的示例.我错了吗?
but REDUCE
selects max date from the whole table and it selects only flat structure, which is not what I want. However, in ABAP examples I saw samples where table-to-table reductions are also possible. Am I wrong?
我尝试的另一件事是使用 WITHOUT MEMBERS
查找唯一值,但此语法不起作用:
Another thing I tried is finding uniques with WITHOUT MEMBERS
but this syntax doesn't work:
it_vend_max = VALUE ty_t_vend( FOR GROUPS value OF <line> IN itab
GROUP BY ( <line>-ven_no <line>-ship_no )
WITHOUT MEMBERS ( lifnr = value
date = nmax( val1 = <line>-date
val2 = value-date ) ) ).
对这里有什么问题的任何建议或自己的优雅解决方案表示赞赏.
Any suggestion of what is wrong here or own elegant solution is appreciated.
推荐答案
如果不是太复杂,我认为最好使用一个构造表达式,这表明该表达式的目标是初始化一个变量而不是其他.
If not too complex, I think it's best to use one construction expression, which shows that the goal of the expression is to initialize one variable and nothing else.
我能做到的最好的表现和最短的可能,但我不能让它优雅:
The best I could do to be the most performing and the shortest possible, but I can't make it elegant:
TYPES ty_ref_s_vend TYPE REF TO ty_s_vend.
result = VALUE ty_t_vend(
FOR GROUPS <group_key> OF <wa> IN itab
GROUP BY ( ven_no = <wa>-ven_no ) ASCENDING
LET max2 = REDUCE #(
INIT max TYPE ty_ref_s_vend
FOR <m> IN GROUP <group_key>
NEXT max = COND #( WHEN max IS NOT BOUND
OR <m>-date > max->*-date
THEN REF #( <m> ) ELSE max ) )
IN ( max2->* ) ).
如您所见,我使用数据引用 (aux_ref_s_vend2
) 来获得更好的性能,以指向具有最新日期的行.理论上它比复制整行的字节更快,但可读性较差.如果你没有大表,使用辅助数据引用和辅助数据对象不会有太大区别.
As you can see I use a data reference (aux_ref_s_vend2
) for a better performance, to point to the line which has the most recent date. It's theoretically faster than copying the bytes of the whole line, but it's less readable. If you don't have a huge table, there won't be a big difference between using an auxiliary data reference or an auxiliary data object.
PS:我无法测试它,因为问题没有提供 MCVE.
PS: I could not test it because the question does not provide a MCVE.
如果您真的想在主构造函数表达式中使用 REDUCE,这是另一种解决方案(但不是必需的):
Here is another solution if you really want to use REDUCE in the primary constructor expression (but it's not needed):
result = REDUCE ty_t_vend(
INIT vend_lines TYPE ty_t_vend
FOR GROUPS <group_key> OF <wa> IN itab
GROUP BY ( ven_no = <wa>-ven_no ) ASCENDING
NEXT vend_lines = VALUE #(
LET max2 = REDUCE ty_ref_s_vend(
INIT max TYPE ty_ref_s_vend
FOR <m> IN GROUP <group_key>
NEXT max = COND #( WHEN max IS NOT BOUND
OR <m>-date > max->*-date
THEN REF #( <m> ) ELSE max ) )
IN BASE vend_lines
( max2->* ) ) ).
这篇关于使用表推导式对 itab 进行分组 + 聚合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!