3

在 ABAP 中,我有一个非常大的内部表,比如 31,000 行。将其拆分为多个固定大小的较小表(例如每个 1,000 行)的最短和最有效的方法是什么?

天真的方式是:

DATA lt_next_package TYPE tt_table_type.
LOOP AT it_large_table INTO DATA(ls_row).
  INSERT ls_row INTO TABLE lt_next_package.
  IF lines( lt_next_package ) >= lc_package_size.
    INSERT lt_next_package INTO TABLE rt_result.
    CLEAR lt_next_package.
  ENDIF.
ENDLOOP.
IF lt_next_package IS NOT INITIAL.
  INSERT lt_next_packge INTO TABLE rt_result.
ENDIF.

这很有效,而且相当有效,但看起来很麻烦,尤其是。最后的不要忘记最后一个包部分。我相信必须有一种更好的方法来使用更新的 ABAP 网格路径和表表达式来做到这一点,但到目前为止还没有想出一个。

4

4 回答 4

1

根据 JozsefSzikszai 的回答,设计了另一种选择:

rt_result = VALUE #( FOR i = 1
                     UNTIL i > round( val = lines( it_large_table) / lc_package_size
                                      dec = 0
                                      mode = cl_abap_math=>round_up )
                     LET lv_end = i * lc_package_size
                         lv_start = lv_end - lc_package_size + 1 IN
                       ( VALUE <result-type>(
                          ( LINES OF it_large_table FROM lv_start TO lv_end ) ) ) ).
于 2018-04-19T10:07:58.703 回答
1

我不确定是否有正确的方法来做到这一点(当然,有几种方法可以做到),但你可以试试这个来克服最后一个包问题:

WHILE it_large_table IS NOT INITIAL.
  LOOP AT it_large_table ASSIGNING FIELD-SYMBOL(<ls_line>) FROM 1 TO 1000.
    INSERT <ls_line> INTO TABLE lt_next_package.
  ENDLOOP.
  DELETE it_large_table FROM 1 TO 1000.
  INSERT lt_next_package INTO TABLE rt_table.
  CLEAR: lt_next_package.
ENDWHILE.
于 2018-04-18T11:27:05.730 回答
0

以下是构建子表 AKA 分页表的两种方法:

METHOD prepare_data.
TYPES:
  BEGIN OF line,
    name  TYPE string,
    subset TYPE salv_t_row,
  END OF line,
  itab TYPE STANDARD TABLE OF line WITH EMPTY KEY.
CONSTANTS: lc_package_size TYPE i VALUE 3.
DATA: result  TYPE itab,
      it_rows TYPE salv_t_row.

DO round( val = lines( it_rows ) / lc_package_size
          dec = 0
          mode = cl_abap_math=>round_up ) TIMES.

  DATA(lv_end) = sy-index * lc_package_size.
  DATA(lv_start) = lv_end - lc_package_size + 1.
  APPEND INITIAL LINE TO result ASSIGNING FIELD-SYMBOL(<subset>).
  <subset>-name = | Subset { sy-index } |.
  <subset>-subset = VALUE #( ( LINES OF it_rows FROM lv_start TO lv_end ) ).
ENDDO.

clear result.

result = VALUE itab( FOR i = 1
                     UNTIL i > round( val = lines( it_rows ) / lc_package_size
                                   dec = 0
                                   mode = cl_abap_math=>round_up )
                     LET k = 1 IN
                     (
                      name = | Subset { i } |
                      subset = VALUE salv_t_row(
                                               LET
                                                  end = i * lc_package_size
                                                  start = end - lc_package_size + 1
                                               IN
                                                  ( LINES OF it_rows from start to end )
                                               )
                     )
                   ).

希望这可以帮助。这里的代码已经过测试并且可以工作。只需复制粘贴(并生成一些数据)。

于 2020-12-31T16:04:37.773 回答
0

对 Florian 和 Jozsef 方法进行了某种改造。

先决条件:

TYPES:
  BEGIN OF line,
    rows TYPE string,
    slice TYPE bseg_t,
  END OF line,
  itab TYPE STANDARD TABLE OF line WITH EMPTY KEY,
  bseg_t TYPE STANDARD TABLE OF bseg WITH EMPTY KEY.
DATA: result TYPE itab.

填充大表:

SELECT * UP TO 31000 ROWS
  INTO TABLE @DATA(lt_bseg)
  FROM bseg.

在这里,我们构建表,其中包含主表的切片,每个切片 1000 行。

WHILE lt_bseg IS NOT INITIAL.
  result = VALUE itab( BASE result
                       (
                       rows  = | { sy-index * 1000 }-{ sy-index * 1000 + 1000} |
                       slice = VALUE bseg_t( FOR wa IN lt_bseg INDEX INTO i FROM i + 1 TO i + 1
                                             ( LINES OF lt_bseg from i TO i + 999 ) )
                       )
                     ).
  DELETE lt_bseg FROM 1 TO 1000.
ENDWHILE.

看起来有点像我们的要求,不是吗?

在此处输入图像描述

于 2018-04-19T18:29:35.057 回答