ABAP New open SQL:FOR ALL ENTRIES IN + BINARY SEARCHから逃れたい

ABAP New open SQL:FOR ALL ENTRIES IN + BINARY SEARCHから逃れたい

SAPが、Code Pushdownと言おうが、
SAPが、Code to Dataと言おうが、
データーベース様には迷惑をかけられない!!!
データーベースはそっとしておきたい!!
(本音では)データーベースを信じてはいけない!
だって、BSEGで先輩たちに怒られ続けたから。

こんなところでしょうか?

だから、ITABにせっせとマスタ情報を溜め込む。
FOR ALL ENTRIES INを使って。
いつしかFOR ALL ENTRIES INを使うために。
準備をして、準備をして、確認して、確認して、えいっ!!てね。
業務ロジックに無関係のコードがたくさん生まれる。
データの並び順に細心の注意を払って。
そしてBINARY SEARCHを使うために下準備を念入りに。

時代は流れてHANAでABAPが動く。
ちょっと前でもORA10。

もうやめようよって思います。
SAPがCode Pushdownって言う遥か前から、一般(非ABAP)と同じようにデータベースにおまかせしようよ。
そう思います。
昔々ORA7とかの頃は信じてはいけなかったかもしれないけれど、もう信じようよ。

っというわけで、FOR ALL ENTRIES IN。
数年前にSAPトレーニング(HA400)を受講したときは、New Open SQLで書き換えできないのはFOR ALL ENTRIES INだけ、あとはRANGE TABLEを含めてすべて書き換え可能と教わりました。
先日、逃げ回っていたFOR ALL ENTRIES INのヘルプを見たら、サンプルコードがNew Open SQLで書かれていました。それと同時に、制約事項もたくさん書かれていました。やっぱり、いろいろ気にしなければいけないことが多いのね。

そこで、これまた先日見つけた必殺技。
「WITH句 + SELECT〜FROM @ITAB」
これ行けます。
FOR ALL ENTRIES INはすべて「WITH句 + SELECT〜FROM @ITAB」で書き換え可能です。そして、使うための下ごしらえもほぼ不要。HANA に一時テーブルという仕組みがあったことを改めて思い出しました。そういえば、HANA Infomation Viewの途中を覗き見するときに、知らないうちに使っていたよな。ABAP 7.52から追加されたWITH句もHANAでは一時テーブルが動いていると考えると辻褄が合うと思います。

プログラムの説明
3種類の方法で、外見上の振る舞いが同じになるように、実装しています。
A:PERFORM START_OF_SELECTION_LOOP1 "FOR ALL ENTRIES IN句を使用してテキスト情報を取得
  コード量(ロジック部分のみ):256行
  従来型の実装です。
  トランザクションデータを使ってFOR ALL ENTRIES IN句でマスタデータをフィルタし取得します。
  BINARY SEARCHでマスタ情報を特定して、各種名称を補完します。
  FOR ALL ENTRIES IN句の直前で、ブランクチェック、SORT命令DELETE命令による重複削除します。
  BINARY SEARCHの手前で、SORT命令による並び替えをします。

B:PERFORM START_OF_SELECTION_LOOP2 "WITH句 + SELECT〜FROM @ITABを使用してテキスト情報を取得
  コード量(ロジック部分のみ):224行
  今回のテーマです。
  WITH句の前半で、トランザクションデータの重複削除します。
  後半でINNER JOINすることでマスタデータのフィルタ取得および、並び替えをします。
  BINARY SEARCHでマスタ情報を特定して、各種名称を補完します。
  直前の、ブランクチェック、SORT命令DELETE命令による重複削除は不要です。
  BINARY SEARCHの手前の並び替えはORDER BY句で行います。

C:PERFORM START_OF_SELECTION_JOIN "テーブルJOINでテキスト情報を取得
  コード量(ロジック部分のみ):62行
  本来あるべき姿
  マスタ情報は、SELECT文のJOIN句で表結合します。

パフォーマンスについて
  約4万件取得で、いずれも0.06~0.07secでした。
 JOINによるパフォーマンス悪化を懸念する人がいると思います。
  以前、単一トランザクションテーブルに対して、約30のマスタテーブルをJOIN句結合しました。
  パフォーマンス悪化は無かったです。(1秒以内で処理終了していました)
 データベースの並列実行に対するパフォーマンス悪化を懸念する人がいると思います。
  数年前に測定したところ、感覚値として50並列位すると、処理時間が1.5倍程度になります。
 個人的には、有り余るSAP HANAのパフォーマンスを遊ばせるのは、エンドユーザの利益と相反すると思います。

ソースコード保守性
 Cの「テーブルJOINでテキスト情報を取得」が圧倒的大差で、コード量が少なくなります。
 (256行→62行:なんと1/4以下!!!)
 コード量が少ないと、バグの入り込む余地が大幅に減ります。
 影響範囲についても、そもそもコード量全体が少ないので、問題にはならないと思います。
 SELECT文については、「情報処理技術者ITパスポート試験」でも出題するので、
 苦手な人は、ご自身のバリューを保つため、勉強しましょう。(むちゃぶり!!?ですか?)

2023-08-14:ラジオボタンで選択できるように修正。

*&---------------------------------------------------------------------*
*& Report SQL_CONSOLE
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT SQL_CONSOLE.

*-----------------------------------------------------------------------
* GLOBAL VARIABLE
*-----------------------------------------------------------------------
DATA:
  GDS_BAPIRET2 TYPE BAPIRET2,                     "リターンパラメータ
  GDF_SUBRC    TYPE SY-SUBRC.                     "リターンコード

*-----------------------------------------------------------------------
* CONDITION VIEW
*-----------------------------------------------------------------------

PARAMETERS P_ISDISP AS CHECKBOX TYPE UFVISIBLE DEFAULT ABAP_FALSE."表示フラグ
PARAMETERS P_TBMAXS TYPE TBMAXSEL DEFAULT 1000000."選択するエントリの最大数
PARAMETERS:
  P_LOOP1 RADIOBUTTON GROUP RB1,                  "FOR ALL ENTRIES IN句を使用してテキスト情報を取得
  P_LOOP2 RADIOBUTTON GROUP RB1,                  "WITH句 + SELECT〜FROM @ITABを使用してテキスト情報を取得
  P_JOIN  RADIOBUTTON GROUP RB1.                  "テーブルJOINでテキスト情報を取得

*-----------------------------------------------------------------------
* START-OF-SELECTION
*-----------------------------------------------------------------------
START-OF-SELECTION.
  CASE ABAP_TRUE.
    WHEN P_LOOP1.
      PERFORM START_OF_SELECTION_LOOP1
        USING
          P_ISDISP                                "表示フラグ
          P_TBMAXS                                "選択するエントリの最大数
        CHANGING
          GDS_BAPIRET2                            "リターンパラメータ
          GDF_SUBRC.                              "リターンコード
      IF GDF_SUBRC <> 0.                          "リターンコード
        LEAVE TO LIST-PROCESSING.
      ENDIF.
    WHEN P_LOOP2.
      PERFORM START_OF_SELECTION_LOOP2
        USING
          P_ISDISP                                "表示フラグ
          P_TBMAXS                                "選択するエントリの最大数
        CHANGING
          GDS_BAPIRET2                            "リターンパラメータ
          GDF_SUBRC.                              "リターンコード
      IF GDF_SUBRC <> 0.                          "リターンコード
        LEAVE TO LIST-PROCESSING.
      ENDIF.
    WHEN P_JOIN.
      PERFORM START_OF_SELECTION_JOIN
        USING
          P_ISDISP                                "表示フラグ
          P_TBMAXS                                "選択するエントリの最大数
        CHANGING
          GDS_BAPIRET2                            "リターンパラメータ
          GDF_SUBRC.                              "リターンコード
      IF GDF_SUBRC <> 0.                          "リターンコード
        LEAVE TO LIST-PROCESSING.
      ENDIF.
    WHEN OTHERS.
      LEAVE TO LIST-PROCESSING.
  ENDCASE.

*-----------------------------------------------------------------------
* SUBROUTINE
*-----------------------------------------------------------------------
FORM START_OF_SELECTION_LOOP1
    USING
      PIF_ISDISP   TYPE CHECKBOX
      PIF_TBMAXSEL TYPE TBMAXSEL
    CHANGING
      POS_BAPIRET2 TYPE BAPIRET2
      POF_SUBRC TYPE SY-SUBRC.
*-----------------------------------------------------------------------
  CLEAR:
      POS_BAPIRET2,                               "リターンパラメータ
      POF_SUBRC.                                  "リターンコード
* Please write the SQL statement here ☆
* Set the internal table to be stored to LDT_DATA ☆
* Inline definition of LDT_DATA is fun ☆
  DATA LDF_TIMESTAMP_START TYPE TIMESTAMPL.       "タイムスタンプデータ取得開始
  GET TIME STAMP FIELD LDF_TIMESTAMP_START.       "タイムスタンプデータ取得開始

  "購買伝票に各種マスタ情報を付加する。
  TYPES:
    BEGIN OF LTS_DATA,                            "一覧データ
      EBELN TYPE EKPO-EBELN,                      "購買伝票番号
      EBELP TYPE EKPO-EBELP,                      "購買伝票の明細番号
      EKORG TYPE EKKO-EKORG,                      "購買組織
      EKOTX TYPE T024E-EKOTX,                     "購買組織テキスト
      EKGRP TYPE EKKO-EKGRP,                      "購買グループ
      EKNAM TYPE T024-EKNAM,                      "購買グループテキスト
      BUKRS TYPE EKKO-BUKRS,                      "会社コード
      BUTXT TYPE T001-BUTXT,                      "会社コードまたは会社の名称
      MATNR TYPE EKPO-MATNR,                      "品目コード
      TXZ01 TYPE EKPO-TXZ01,                      "テキスト (短)
      WERKS TYPE EKPO-WERKS,                      "プラント
      NAME1 TYPE T001W-NAME1,                     "名称
      LGORT TYPE EKPO-LGORT,                      "保管場所
      LGOBE TYPE T001L-LGOBE,                     "保管場所テキスト
      MENGE TYPE EKPO-MENGE,                      "購買発注量
      MEINS TYPE EKPO-MEINS,                      "発注単位
    END OF LTS_DATA,
    LTT_DATA TYPE STANDARD TABLE OF LTS_DATA,     "一覧データ

    BEGIN OF LTS_T024E,                           "購買組織
      EKORG TYPE T024E-EKORG,                     "購買組織
      EKOTX TYPE T024E-EKOTX,                     "購買組織テキスト
    END OF LTS_T024E,
    LTT_T024E TYPE STANDARD TABLE OF LTS_T024E,   "購買組織

    BEGIN OF LTS_T024,                            "購買グループ
      EKGRP TYPE T024-EKGRP,                      "購買グループ
      EKNAM TYPE T024-EKNAM,                      "購買グループテキスト
    END OF LTS_T024,
    LTT_T024 TYPE STANDARD TABLE OF LTS_T024,     "購買グループ

    BEGIN OF LTS_T001,                            "会社コード
      BUKRS TYPE T001-BUKRS,                      "会社コード
      BUTXT TYPE T001-BUTXT,                      "会社コードまたは会社の名称
    END OF LTS_T001,
    LTT_T001 TYPE STANDARD TABLE OF LTS_T001,     "会社コード

    BEGIN OF LTS_T001W,                           "プラント/支店
      WERKS TYPE T001W-WERKS,                     "プラント
      NAME1 TYPE T001W-NAME1,                     "名称
    END OF LTS_T001W,
    LTT_T001W TYPE STANDARD TABLE OF LTS_T001W,   "プラント/支店

    BEGIN OF LTS_T001L,                           "保管場所
      WERKS TYPE T001L-WERKS,                     "プラント
      LGORT TYPE T001L-LGORT,                     "保管場所
      LGOBE TYPE T001L-LGOBE,                     "保管場所テキスト
    END OF LTS_T001L,
    LTT_T001L TYPE STANDARD TABLE OF LTS_T001L.   "保管場所

  DATA:
    LDT_DATA  TYPE LTT_DATA,                      "一覧データ
    LDT_DATA1 TYPE LTT_DATA,                      "一覧データ:作業用

    LDT_T024E TYPE LTT_T024E,                     "購買組織
    LDS_T024E LIKE LINE OF LDT_T024E,             "購買組織
    LDT_T024  TYPE LTT_T024,                      "購買グループ
    LDS_T024  LIKE LINE OF LDT_T024,              "購買グループ
    LDT_T001  TYPE LTT_T001,                      "会社コード
    LDS_T001  LIKE LINE OF LDT_T001,              "会社コード
    LDT_T001W TYPE LTT_T001W,                     "プラント/支店
    LDS_T001W LIKE LINE OF LDT_T001W,             "プラント/支店
    LDT_T001L TYPE LTT_T001L,                     "保管場所
    LDS_T001L LIKE LINE OF LDT_T001L.             "保管場所

  SELECT
      EKPO~EBELN,                                 "購買伝票番号
      EKPO~EBELP,                                 "購買伝票の明細番号
      EKKO~EKORG,                                 "購買組織
      EKKO~EKGRP,                                 "購買グループ
      EKKO~BUKRS,                                 "会社コード
      EKPO~MATNR,                                 "品目コード
      EKPO~TXZ01,                                 "テキスト (短)
      EKPO~WERKS,                                 "プラント
      EKPO~LGORT,                                 "保管場所
      EKPO~MENGE,                                 "購買発注量
      EKPO~MEINS                                  "発注単位
    FROM EKPO                                     "購買伝票明細
    INNER JOIN EKKO                               "購買伝票ヘッダ
       ON EKKO~EBELN = EKPO~EBELN                 "購買伝票番号
    ORDER BY
      EKPO~EBELN,                                 "購買伝票番号
      EKPO~EBELP                                  "購買伝票の明細番号
    INTO CORRESPONDING FIELDS OF TABLE @LDT_DATA. "一覧データ
  IF SY-SUBRC <> 0.
    POF_SUBRC = 4.
    RETURN.
  ENDIF.

  CLEAR LDT_DATA1.                                "一覧データ:作業用
  LDT_DATA1 = LDT_DATA.                           "一覧データ:作業用
  SORT LDT_DATA1 ASCENDING BY                     "一覧データ:作業用
      EKORG.                                      "購買組織
  DELETE ADJACENT DUPLICATES FROM LDT_DATA1 COMPARING"一覧データ:作業用
      EKORG.                                      "購買組織
  IF LDT_DATA1 IS NOT INITIAL.                    "一覧データ:作業用
    SELECT
        T024E~EKORG,                              "購買組織
        T024E~EKOTX                               "購買組織テキスト
      FROM T024E                                  "購買組織
      FOR ALL ENTRIES IN @LDT_DATA1               "一覧データ:作業用
      WHERE T024E~EKORG = @LDT_DATA1-EKORG        "購買組織
      INTO TABLE @LDT_T024E.                      "購買組織
    IF SY-SUBRC = 0.
      SORT LDT_T024E ASCENDING BY                 "購買組織
          EKORG.                                  "購買組織
      DELETE ADJACENT DUPLICATES FROM LDT_T024E COMPARING"購買組織
          EKORG.                                  "購買組織
    ENDIF.
  ENDIF.

  CLEAR LDT_DATA1.                                "一覧データ:作業用
  LDT_DATA1 = LDT_DATA.                           "一覧データ:作業用
  SORT LDT_DATA1 ASCENDING BY                     "一覧データ:作業用
      EKGRP.
  DELETE ADJACENT DUPLICATES FROM LDT_DATA1 COMPARING"一覧データ:作業用
      EKGRP.
  IF LDT_DATA1 IS NOT INITIAL.                    "一覧データ:作業用
    SELECT
        T024~EKGRP,                               "購買グループ
        T024~EKNAM                                "購買グループテキスト
      FROM T024                                   "購買グループ
      FOR ALL ENTRIES IN @LDT_DATA1               "一覧データ:作業用
      WHERE T024~EKGRP = @LDT_DATA1-EKGRP         "購買グループ
      INTO TABLE @LDT_T024.                       "購買グループ
    IF SY-SUBRC = 0.
      SORT LDT_T024 ASCENDING BY                  "購買グループ
          EKGRP.                                  "購買グループ
      DELETE ADJACENT DUPLICATES FROM LDT_T024 COMPARING"購買グループ
          EKGRP.                                  "購買グループ
    ENDIF.
  ENDIF.

  CLEAR LDT_DATA1.                                "一覧データ:作業用
  LDT_DATA1 = LDT_DATA.                           "一覧データ:作業用
  SORT LDT_DATA1 ASCENDING BY                     "一覧データ:作業用
      BUKRS.
  DELETE ADJACENT DUPLICATES FROM LDT_DATA1 COMPARING"一覧データ:作業用
      BUKRS.
  IF LDT_DATA1 IS NOT INITIAL.                    "一覧データ:作業用
    SELECT
        T001~BUKRS,                               "会社コード
        T001~BUTXT                                "会社コードまたは会社の名称
      FROM T001
      FOR ALL ENTRIES IN @LDT_DATA1               "一覧データ:作業用
      WHERE T001~BUKRS = @LDT_DATA1-BUKRS         "会社コード
      INTO TABLE @LDT_T001.                       "会社コード
    IF SY-SUBRC = 0.
      SORT LDT_T001 ASCENDING BY                  "会社コード
          BUKRS.                                  "会社コード
      DELETE ADJACENT DUPLICATES FROM LDT_T001 COMPARING"会社コード
          BUKRS.                                  "会社コード
    ENDIF.
  ENDIF.

  CLEAR LDT_DATA1.                                "一覧データ:作業用
  LDT_DATA1 = LDT_DATA.                           "一覧データ:作業用
  SORT LDT_DATA1 ASCENDING BY                     "一覧データ:作業用
      WERKS.
  DELETE ADJACENT DUPLICATES FROM LDT_DATA1 COMPARING"一覧データ:作業用
      WERKS.
  IF LDT_DATA1 IS NOT INITIAL.                    "一覧データ:作業用
    SELECT
        T001W~WERKS,                              "プラント
        T001W~NAME1                               "名称
      FROM T001W                                  "プラント/支店
      FOR ALL ENTRIES IN @LDT_DATA1               "一覧データ:作業用
      WHERE T001W~WERKS = @LDT_DATA1-WERKS        "プラント
      INTO TABLE @LDT_T001W.                      "プラント/支店
    IF SY-SUBRC = 0.
      SORT LDT_T001W ASCENDING BY                 "プラント/支店
          WERKS.                                  "プラント
      DELETE ADJACENT DUPLICATES FROM LDT_T001W COMPARING"プラント/支店
          WERKS.                                  "プラント
    ENDIF.
  ENDIF.

  CLEAR LDT_DATA1.                                "一覧データ:作業用
  LDT_DATA1 = LDT_DATA.                           "一覧データ:作業用
  SORT LDT_DATA1 ASCENDING BY                     "一覧データ:作業用
      WERKS                                       "プラント
      LGORT.                                      "保管場所
  DELETE ADJACENT DUPLICATES FROM LDT_DATA1 COMPARING"一覧データ:作業用
      WERKS                                       "プラント
      LGORT.                                      "保管場所
  IF LDT_DATA1 IS NOT INITIAL.                    "一覧データ:作業用
    SELECT
        T001L~WERKS,                              "プラント
        T001L~LGORT,                              "保管場所
        T001L~LGOBE                               "保管場所テキスト
      FROM T001L                                  "保管場所
      FOR ALL ENTRIES IN @LDT_DATA1               "一覧データ:作業用
      WHERE T001L~WERKS = @LDT_DATA1-WERKS        "プラント
        AND T001L~LGORT = @LDT_DATA1-LGORT        "保管場所
      INTO TABLE @LDT_T001L.                      "保管場所
    IF SY-SUBRC = 0.
      SORT LDT_T001L ASCENDING BY                 "保管場所
          WERKS                                   "プラント
          LGORT.                                  "保管場所
      DELETE ADJACENT DUPLICATES FROM LDT_T001L COMPARING
          WERKS                                   "プラント
          LGORT.                                  "保管場所
    ENDIF.
  ENDIF.

  LOOP AT LDT_DATA ASSIGNING FIELD-SYMBOL(<LFS_DATA>)."一覧データ

    CLEAR LDS_T024E.                              "購買組織
    READ TABLE LDT_T024E WITH KEY                 "購買組織
        EKORG = <LFS_DATA>-EKORG                  "購買組織
      BINARY SEARCH
      INTO LDS_T024E.                             "購買組織
    IF SY-SUBRC = 0.
      <LFS_DATA>-EKOTX = LDS_T024E-EKOTX.         "購買組織テキスト
    ENDIF.

    CLEAR LDS_T024.                               "購買グループ
    READ TABLE LDT_T024 WITH KEY                  "購買グループ
        EKGRP = <LFS_DATA>-EKGRP                  "購買グループ
      BINARY SEARCH
      INTO LDS_T024.                              "購買グループ
    IF SY-SUBRC = 0.
      <LFS_DATA>-EKNAM = LDS_T024-EKNAM.          "購買グループテキスト
    ENDIF.

    CLEAR LDS_T001.                               "会社コード
    READ TABLE LDT_T001 WITH KEY                  "会社コード
        BUKRS = <LFS_DATA>-BUKRS                  "会社コード
      BINARY SEARCH
      INTO LDS_T001.                              "会社コード
    IF SY-SUBRC = 0.
      <LFS_DATA>-BUTXT = LDS_T001-BUTXT.          "会社コードまたは会社の名称
    ENDIF.

    CLEAR LDS_T001W.                              "プラント/支店
    READ TABLE LDT_T001W WITH KEY                 "プラント/支店
        WERKS = <LFS_DATA>-WERKS                  "プラント
      BINARY SEARCH
      INTO LDS_T001W.                             "プラント/支店
    IF SY-SUBRC = 0.
      <LFS_DATA>-NAME1 = LDS_T001W-NAME1.         "名称
    ENDIF.

    CLEAR LDS_T001L.                              "保管場所
    READ TABLE LDT_T001L WITH KEY                 "保管場所
        WERKS = <LFS_DATA>-WERKS                  "プラント
        LGORT = <LFS_DATA>-LGORT                  "保管場所
      BINARY SEARCH
      INTO LDS_T001L.                             "保管場所
    IF SY-SUBRC = 0.
      <LFS_DATA>-LGOBE = LDS_T001L-LGOBE.         "保管場所テキスト
    ENDIF.

  ENDLOOP.

  DATA LDF_TIMESTAMP_END TYPE TIMESTAMPL.         "タイムスタンプデータ取得終了
  GET TIME STAMP FIELD LDF_TIMESTAMP_END.         "タイムスタンプデータ取得終了
  DATA(LDF_DATA_COUNT) = LINES( LDT_DATA ).
  IF PIF_ISDISP = ABAP_FALSE.
    CLEAR LDT_DATA.
  ENDIF.
*-----------------------------------------------------------------------
  TRY.
      CL_SALV_TABLE=>FACTORY(
        IMPORTING
          R_SALV_TABLE = DATA(LDO_ALV)
        CHANGING
          T_TABLE      = LDT_DATA ).
    CATCH CX_SALV_MSG INTO DATA(LDX_SALV_MSG).
      POF_SUBRC = 8.
      RETURN.
  ENDTRY.

  DATA(LDO_HEADER) = NEW CL_SALV_FORM_LAYOUT_GRID( ).
  LDO_ALV->SET_TOP_OF_LIST( LDO_HEADER ).
  LDO_HEADER->CREATE_LABEL( ROW = 1 COLUMN = 1 TEXT = 'Performance data' ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 1 TEXT = 'Input records' ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 2 TEXT = 'EKPO' ).
  SELECT FROM EKPO FIELDS COUNT(*) INTO @DATA(LDF_COUNT3).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 3 TEXT = LDF_COUNT3 ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 4 TEXT = 'EKKO' ).
  SELECT FROM EKKO FIELDS COUNT(*) INTO @DATA(LDF_COUNT5).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 5 TEXT = LDF_COUNT5 ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 6 TEXT = 'T001' ).
  SELECT FROM T001 FIELDS COUNT(*) INTO @DATA(LDF_COUNT7).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 7 TEXT = LDF_COUNT7 ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 8 TEXT = 'T024' ).
  SELECT FROM T024 FIELDS COUNT(*) INTO @DATA(LDF_COUNT9).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 9 TEXT = LDF_COUNT9 ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 10 TEXT = 'T024E' ).
  SELECT FROM T024E FIELDS COUNT(*) INTO @DATA(LDF_COUNT11).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 11 TEXT = LDF_COUNT11 ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 12 TEXT = 'T001W' ).
  SELECT FROM T001W FIELDS COUNT(*) INTO @DATA(LDF_COUNT13).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 13 TEXT = LDF_COUNT13 ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 14 TEXT = 'T001L' ).
  SELECT FROM T001L FIELDS COUNT(*) INTO @DATA(LDF_COUNT15).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 15 TEXT = LDF_COUNT15 ).
  LDO_HEADER->CREATE_TEXT( ROW = 3 COLUMN = 1 TEXT = 'Output records' ).
  LDO_HEADER->CREATE_TEXT( ROW = 3 COLUMN = 2 TEXT = LDF_DATA_COUNT ).
  LDO_HEADER->CREATE_TEXT( ROW = 4 COLUMN = 1 TEXT = 'Responce Time [sec]' ).
  LDO_HEADER->CREATE_TEXT( ROW = 4 COLUMN = 2 TEXT = CL_ABAP_TSTMP=>SUBTRACT( TSTMP1 = LDF_TIMESTAMP_END TSTMP2 = LDF_TIMESTAMP_START ) ).

  LDO_ALV->SET_TOP_OF_LIST( LDO_HEADER ).
  LDO_ALV->SET_TOP_OF_LIST_PRINT( LDO_HEADER ).

  LDO_ALV->GET_FUNCTIONS( )->SET_ALL( ).
  LDO_ALV->GET_COLUMNS( )->SET_OPTIMIZE( ).
  LDO_ALV->GET_DISPLAY_SETTINGS( )->SET_STRIPED_PATTERN( ABAP_TRUE ).
  LDO_ALV->GET_SELECTIONS( )->SET_SELECTION_MODE( VALUE = IF_SALV_C_SELECTION_MODE=>CELL ).
  LDO_ALV->DISPLAY( ).

  POF_SUBRC = 0.
ENDFORM.

FORM START_OF_SELECTION_LOOP2
    USING
      PIF_ISDISP   TYPE CHECKBOX
      PIF_TBMAXSEL TYPE TBMAXSEL
    CHANGING
      POS_BAPIRET2 TYPE BAPIRET2
      POF_SUBRC TYPE SY-SUBRC.
*-----------------------------------------------------------------------
  CLEAR:
      POS_BAPIRET2,                               "リターンパラメータ
      POF_SUBRC.                                  "リターンコード
* Please write the SQL statement here ☆
* Set the internal table to be stored to LDT_DATA ☆
* Inline definition of LDT_DATA is fun ☆
  DATA LDF_TIMESTAMP_START TYPE TIMESTAMPL.       "タイムスタンプデータ取得開始
  GET TIME STAMP FIELD LDF_TIMESTAMP_START.       "タイムスタンプデータ取得開始

  "購買伝票に各種マスタ情報を付加する。
  TYPES:
    BEGIN OF LTS_DATA,                            "一覧データ
      EBELN TYPE EKPO-EBELN,                      "購買伝票番号
      EBELP TYPE EKPO-EBELP,                      "購買伝票の明細番号
      EKORG TYPE EKKO-EKORG,                      "購買組織
      EKOTX TYPE T024E-EKOTX,                     "購買組織テキスト
      EKGRP TYPE EKKO-EKGRP,                      "購買グループ
      EKNAM TYPE T024-EKNAM,                      "購買グループテキスト
      BUKRS TYPE EKKO-BUKRS,                      "会社コード
      BUTXT TYPE T001-BUTXT,                      "会社コードまたは会社の名称
      MATNR TYPE EKPO-MATNR,                      "品目コード
      TXZ01 TYPE EKPO-TXZ01,                      "テキスト (短)
      WERKS TYPE EKPO-WERKS,                      "プラント
      NAME1 TYPE T001W-NAME1,                     "名称
      LGORT TYPE EKPO-LGORT,                      "保管場所
      LGOBE TYPE T001L-LGOBE,                     "保管場所テキスト
      MENGE TYPE EKPO-MENGE,                      "購買発注量
      MEINS TYPE EKPO-MEINS,                      "発注単位
    END OF LTS_DATA,
    LTT_DATA TYPE STANDARD TABLE OF LTS_DATA,     "一覧データ

    BEGIN OF LTS_T024E,                           "購買組織
      EKORG TYPE T024E-EKORG,                     "購買組織
      EKOTX TYPE T024E-EKOTX,                     "購買組織テキスト
    END OF LTS_T024E,
    LTT_T024E TYPE STANDARD TABLE OF LTS_T024E,   "購買組織

    BEGIN OF LTS_T024,                            "購買グループ
      EKGRP TYPE T024-EKGRP,                      "購買グループ
      EKNAM TYPE T024-EKNAM,                      "購買グループテキスト
    END OF LTS_T024,
    LTT_T024 TYPE STANDARD TABLE OF LTS_T024,     "購買グループ

    BEGIN OF LTS_T001,                            "会社コード
      BUKRS TYPE T001-BUKRS,                      "会社コード
      BUTXT TYPE T001-BUTXT,                      "会社コードまたは会社の名称
    END OF LTS_T001,
    LTT_T001 TYPE STANDARD TABLE OF LTS_T001,     "会社コード

    BEGIN OF LTS_T001W,                           "プラント/支店
      WERKS TYPE T001W-WERKS,                     "プラント
      NAME1 TYPE T001W-NAME1,                     "名称
    END OF LTS_T001W,
    LTT_T001W TYPE STANDARD TABLE OF LTS_T001W,   "プラント/支店

    BEGIN OF LTS_T001L,                           "保管場所
      WERKS TYPE T001L-WERKS,                     "プラント
      LGORT TYPE T001L-LGORT,                     "保管場所
      LGOBE TYPE T001L-LGOBE,                     "保管場所テキスト
    END OF LTS_T001L,
    LTT_T001L TYPE STANDARD TABLE OF LTS_T001L.   "保管場所

  DATA:
    LDT_DATA  TYPE LTT_DATA,                      "一覧データ

    LDT_T024E TYPE LTT_T024E,                     "購買組織
    LDS_T024E LIKE LINE OF LDT_T024E,             "購買組織
    LDT_T024  TYPE LTT_T024,                      "購買グループ
    LDS_T024  LIKE LINE OF LDT_T024,              "購買グループ
    LDT_T001  TYPE LTT_T001,                      "会社コード
    LDS_T001  LIKE LINE OF LDT_T001,              "会社コード
    LDT_T001W TYPE LTT_T001W,                     "プラント/支店
    LDS_T001W LIKE LINE OF LDT_T001W,             "プラント/支店
    LDT_T001L TYPE LTT_T001L,                     "保管場所
    LDS_T001L LIKE LINE OF LDT_T001L.             "保管場所

  SELECT
      EKPO~EBELN,                                 "購買伝票番号
      EKPO~EBELP,                                 "購買伝票の明細番号
      EKKO~EKORG,                                 "購買組織
      EKKO~EKGRP,                                 "購買グループ
      EKKO~BUKRS,                                 "会社コード
      EKPO~MATNR,                                 "品目コード
      EKPO~TXZ01,                                 "テキスト (短)
      EKPO~WERKS,                                 "プラント
      EKPO~LGORT,                                 "保管場所
      EKPO~MENGE,                                 "購買発注量
      EKPO~MEINS                                  "発注単位
    FROM EKPO                                     "購買伝票明細
    INNER JOIN EKKO                               "購買伝票ヘッダ
       ON EKKO~EBELN = EKPO~EBELN                 "購買伝票番号
    ORDER BY
      EKPO~EBELN,                                 "購買伝票番号
      EKPO~EBELP                                  "購買伝票の明細番号
    INTO CORRESPONDING FIELDS OF TABLE @LDT_DATA. "一覧データ
  IF SY-SUBRC <> 0.
    POF_SUBRC = 4.
    RETURN.
  ENDIF.

  WITH
  +LDT_DATA AS ( SELECT                           "一覧データ
      LDT_DATA~EKORG                              "購買組織
    FROM @LDT_DATA AS LDT_DATA                    "一覧データ
    GROUP BY
      LDT_DATA~EKORG )                            "購買組織
  SELECT
      T024E~EKORG,                                "購買組織
      T024E~EKOTX                                 "購買組織テキスト
    FROM T024E                                    "購買組織
    INNER JOIN +LDT_DATA                          "一覧データ
       ON +LDT_DATA~EKORG = T024E~EKORG           "購買組織
    ORDER BY
      T024E~EKORG                                 "購買組織
    INTO TABLE @LDT_T024E.                        "購買組織

  WITH
  +LDT_DATA AS ( SELECT                           "一覧データ
      LDT_DATA~EKGRP                              "購買グループ
    FROM @LDT_DATA AS LDT_DATA                    "一覧データ
    GROUP BY
      LDT_DATA~EKGRP )                            "購買グループ
  SELECT
      T024~EKGRP,                                 "購買グループ
      T024~EKNAM                                  "購買グループテキスト
    FROM T024                                     "購買グループ
    INNER JOIN +LDT_DATA                          "一覧データ
       ON +LDT_DATA~EKGRP = T024~EKGRP            "購買グループ
    ORDER BY
      T024~EKGRP                                  "購買グループ
    INTO TABLE @LDT_T024.                         "購買グループ

  WITH
  +LDT_DATA AS ( SELECT                           "一覧データ
      LDT_DATA~BUKRS                              "会社コード
    FROM @LDT_DATA AS LDT_DATA                    "一覧データ
    GROUP BY
      LDT_DATA~BUKRS )                            "会社コード
  SELECT
      T001~BUKRS,                                 "会社コード
      T001~BUTXT                                  "会社コードまたは会社の名称
    FROM T001                                     "会社コード
    INNER JOIN +LDT_DATA                          "一覧データ
       ON +LDT_DATA~BUKRS = T001~BUKRS            "会社コード
    ORDER BY
      T001~BUKRS                                  "会社コード
    INTO TABLE @LDT_T001.                         "会社コード

  WITH
  +LDT_DATA AS ( SELECT                           "一覧データ
      LDT_DATA~WERKS                              "プラント
    FROM @LDT_DATA AS LDT_DATA                    "一覧データ
    GROUP BY
      LDT_DATA~WERKS )                            "プラント
  SELECT
      T001W~WERKS,                                "プラント
      T001W~NAME1                                 "名称
    FROM T001W                                    "プラント/支店
    INNER JOIN +LDT_DATA                          "一覧データ
       ON +LDT_DATA~WERKS = T001W~WERKS           "プラント
    ORDER BY
      T001W~WERKS                                 "プラント
    INTO TABLE @LDT_T001W.                        "プラント/支店

  WITH
  +LDT_DATA AS ( SELECT                           "一覧データ
      LDT_DATA~WERKS,                             "プラント
      LDT_DATA~LGORT                              "保管場所
    FROM @LDT_DATA AS LDT_DATA                    "一覧データ
    GROUP BY
      LDT_DATA~WERKS,                             "プラント
      LDT_DATA~LGORT )                            "保管場所
  SELECT
      T001L~WERKS,                                "プラント
      T001L~LGORT,                                "保管場所
      T001L~LGOBE                                 "保管場所テキスト
    FROM T001L                                    "保管場所
    INNER JOIN +LDT_DATA                          "一覧データ
       ON +LDT_DATA~WERKS = T001L~WERKS           "プラント
      AND +LDT_DATA~LGORT = T001L~LGORT           "保管場所
    ORDER BY
      T001L~WERKS,                                "プラント
      T001L~LGORT                                 "保管場所
    INTO TABLE @LDT_T001L.                        "保管場所

  LOOP AT LDT_DATA ASSIGNING FIELD-SYMBOL(<LFS_DATA>)."一覧データ

    CLEAR LDS_T024E.                              "購買組織
    READ TABLE LDT_T024E WITH KEY                 "購買組織
        EKORG = <LFS_DATA>-EKORG                  "購買組織
      BINARY SEARCH
      INTO LDS_T024E.                             "購買組織
    IF SY-SUBRC = 0.
      <LFS_DATA>-EKOTX = LDS_T024E-EKOTX.         "購買組織テキスト
    ENDIF.

    CLEAR LDS_T024.                               "購買グループ
    READ TABLE LDT_T024 WITH KEY                  "購買グループ
        EKGRP = <LFS_DATA>-EKGRP                  "購買グループ
      BINARY SEARCH
      INTO LDS_T024.                              "購買グループ
    IF SY-SUBRC = 0.
      <LFS_DATA>-EKNAM = LDS_T024-EKNAM.          "購買グループテキスト
    ENDIF.

    CLEAR LDS_T001.                               "会社コード
    READ TABLE LDT_T001 WITH KEY                  "会社コード
        BUKRS = <LFS_DATA>-BUKRS                  "会社コード
      BINARY SEARCH
      INTO LDS_T001.                              "会社コード
    IF SY-SUBRC = 0.
      <LFS_DATA>-BUTXT = LDS_T001-BUTXT.          "会社コードまたは会社の名称
    ENDIF.

    CLEAR LDS_T001W.                              "プラント/支店
    READ TABLE LDT_T001W WITH KEY                 "プラント/支店
        WERKS = <LFS_DATA>-WERKS                  "プラント
      BINARY SEARCH
      INTO LDS_T001W.                             "プラント/支店
    IF SY-SUBRC = 0.
      <LFS_DATA>-NAME1 = LDS_T001W-NAME1.         "名称
    ENDIF.

    CLEAR LDS_T001L.                              "保管場所
    READ TABLE LDT_T001L WITH KEY                 "保管場所
        WERKS = <LFS_DATA>-WERKS                  "プラント
        LGORT = <LFS_DATA>-LGORT                  "保管場所
      BINARY SEARCH
      INTO LDS_T001L.                             "保管場所
    IF SY-SUBRC = 0.
      <LFS_DATA>-LGOBE = LDS_T001L-LGOBE.         "保管場所テキスト
    ENDIF.

  ENDLOOP.

  DATA LDF_TIMESTAMP_END TYPE TIMESTAMPL.         "タイムスタンプデータ取得終了
  GET TIME STAMP FIELD LDF_TIMESTAMP_END.         "タイムスタンプデータ取得終了
  DATA(LDF_DATA_COUNT) = LINES( LDT_DATA ).
  IF PIF_ISDISP = ABAP_FALSE.
    CLEAR LDT_DATA.
  ENDIF.
*-----------------------------------------------------------------------
  TRY.
      CL_SALV_TABLE=>FACTORY(
        IMPORTING
          R_SALV_TABLE = DATA(LDO_ALV)
        CHANGING
          T_TABLE      = LDT_DATA ).
    CATCH CX_SALV_MSG INTO DATA(LDX_SALV_MSG).
      POF_SUBRC = 8.
      RETURN.
  ENDTRY.

  DATA(LDO_HEADER) = NEW CL_SALV_FORM_LAYOUT_GRID( ).
  LDO_ALV->SET_TOP_OF_LIST( LDO_HEADER ).
  LDO_HEADER->CREATE_LABEL( ROW = 1 COLUMN = 1 TEXT = 'Performance data' ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 1 TEXT = 'Input records' ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 2 TEXT = 'EKPO' ).
  SELECT FROM EKPO FIELDS COUNT(*) INTO @DATA(LDF_COUNT3).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 3 TEXT = LDF_COUNT3 ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 4 TEXT = 'EKKO' ).
  SELECT FROM EKKO FIELDS COUNT(*) INTO @DATA(LDF_COUNT5).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 5 TEXT = LDF_COUNT5 ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 6 TEXT = 'T001' ).
  SELECT FROM T001 FIELDS COUNT(*) INTO @DATA(LDF_COUNT7).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 7 TEXT = LDF_COUNT7 ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 8 TEXT = 'T024' ).
  SELECT FROM T024 FIELDS COUNT(*) INTO @DATA(LDF_COUNT9).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 9 TEXT = LDF_COUNT9 ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 10 TEXT = 'T024E' ).
  SELECT FROM T024E FIELDS COUNT(*) INTO @DATA(LDF_COUNT11).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 11 TEXT = LDF_COUNT11 ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 12 TEXT = 'T001W' ).
  SELECT FROM T001W FIELDS COUNT(*) INTO @DATA(LDF_COUNT13).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 13 TEXT = LDF_COUNT13 ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 14 TEXT = 'T001L' ).
  SELECT FROM T001L FIELDS COUNT(*) INTO @DATA(LDF_COUNT15).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 15 TEXT = LDF_COUNT15 ).
  LDO_HEADER->CREATE_TEXT( ROW = 3 COLUMN = 1 TEXT = 'Output records' ).
  LDO_HEADER->CREATE_TEXT( ROW = 3 COLUMN = 2 TEXT = LDF_DATA_COUNT ).
  LDO_HEADER->CREATE_TEXT( ROW = 4 COLUMN = 1 TEXT = 'Responce Time [sec]' ).
  LDO_HEADER->CREATE_TEXT( ROW = 4 COLUMN = 2 TEXT = CL_ABAP_TSTMP=>SUBTRACT( TSTMP1 = LDF_TIMESTAMP_END TSTMP2 = LDF_TIMESTAMP_START ) ).

  LDO_ALV->SET_TOP_OF_LIST( LDO_HEADER ).
  LDO_ALV->SET_TOP_OF_LIST_PRINT( LDO_HEADER ).

  LDO_ALV->GET_FUNCTIONS( )->SET_ALL( ).
  LDO_ALV->GET_COLUMNS( )->SET_OPTIMIZE( ).
  LDO_ALV->GET_DISPLAY_SETTINGS( )->SET_STRIPED_PATTERN( ABAP_TRUE ).
  LDO_ALV->GET_SELECTIONS( )->SET_SELECTION_MODE( VALUE = IF_SALV_C_SELECTION_MODE=>CELL ).
  LDO_ALV->DISPLAY( ).

  POF_SUBRC = 0.
ENDFORM.

FORM START_OF_SELECTION_JOIN
    USING
      PIF_ISDISP   TYPE CHECKBOX
      PIF_TBMAXSEL TYPE TBMAXSEL
    CHANGING
      POS_BAPIRET2 TYPE BAPIRET2
      POF_SUBRC TYPE SY-SUBRC.
*-----------------------------------------------------------------------
  CLEAR:
      POS_BAPIRET2,                               "リターンパラメータ
      POF_SUBRC.                                  "リターンコード
* Please write the SQL statement here ☆
* Set the internal table to be stored to LDT_DATA ☆
* Inline definition of LDT_DATA is fun ☆
  DATA LDF_TIMESTAMP_START TYPE TIMESTAMPL.       "タイムスタンプデータ取得開始
  GET TIME STAMP FIELD LDF_TIMESTAMP_START.       "タイムスタンプデータ取得開始

  "購買伝票に各種マスタ情報を付加する。
  TYPES:
    BEGIN OF LTS_DATA,                            "一覧データ
      EBELN TYPE EKPO-EBELN,                      "購買伝票番号
      EBELP TYPE EKPO-EBELP,                      "購買伝票の明細番号
      EKORG TYPE EKKO-EKORG,                      "購買組織
      EKOTX TYPE T024E-EKOTX,                     "購買組織テキスト
      EKGRP TYPE EKKO-EKGRP,                      "購買グループ
      EKNAM TYPE T024-EKNAM,                      "購買グループテキスト
      BUKRS TYPE EKKO-BUKRS,                      "会社コード
      BUTXT TYPE T001-BUTXT,                      "会社コードまたは会社の名称
      MATNR TYPE EKPO-MATNR,                      "品目コード
      TXZ01 TYPE EKPO-TXZ01,                      "テキスト (短)
      WERKS TYPE EKPO-WERKS,                      "プラント
      NAME1 TYPE T001W-NAME1,                     "名称
      LGORT TYPE EKPO-LGORT,                      "保管場所
      LGOBE TYPE T001L-LGOBE,                     "保管場所テキスト
      MENGE TYPE EKPO-MENGE,                      "購買発注量
      MEINS TYPE EKPO-MEINS,                      "発注単位
    END OF LTS_DATA,
    LTT_DATA TYPE STANDARD TABLE OF LTS_DATA.     "一覧データ
  DATA:
    LDT_DATA TYPE LTT_DATA.                       "一覧データ

  SELECT
      EKPO~EBELN,                                 "購買伝票番号
      EKPO~EBELP,                                 "購買伝票の明細番号
      EKKO~EKORG,                                 "購買組織
      T024E~EKOTX,                                "購買組織テキスト
      EKKO~EKGRP,                                 "購買グループ
      T024~EKNAM,                                 "購買グループテキスト
      EKKO~BUKRS,                                 "会社コード
      T001~BUTXT,                                 "会社コードまたは会社の名称
      EKPO~MATNR,                                 "品目コード
      EKPO~TXZ01,                                 "テキスト (短)
      EKPO~WERKS,                                 "プラント
      T001W~NAME1,                                "名称
      EKPO~LGORT,                                 "保管場所
      T001L~LGOBE,                                "保管場所テキスト
      EKPO~MENGE,                                 "購買発注量
      EKPO~MEINS                                  "発注単位
    FROM EKPO                                     "購買伝票明細
    INNER JOIN EKKO                               "購買伝票ヘッダ
       ON EKKO~EBELN = EKPO~EBELN                 "購買伝票番号
    LEFT OUTER JOIN T024E                         "購買組織
       ON T024E~EKORG = EKKO~EKORG                "購買組織
    LEFT OUTER JOIN T024                          "購買グループ
       ON T024~EKGRP = EKKO~EKGRP                 "購買グループ
    LEFT OUTER JOIN T001                          "会社コード
       ON T001~BUKRS = EKKO~BUKRS                 "会社コード
    LEFT OUTER JOIN T001W                         "プラント/支店
       ON T001W~WERKS = EKPO~WERKS                "プラント
    LEFT OUTER JOIN T001L                         "保管場所
       ON T001L~WERKS = EKPO~WERKS                "プラント
      AND T001L~LGORT = EKPO~LGORT                "保管場所
    ORDER BY
      EKPO~EBELN,                                 "購買伝票番号
      EKPO~EBELP                                  "購買伝票の明細番号
    INTO TABLE @LDT_DATA.                         "一覧データ
  IF SY-SUBRC <> 0.
    POF_SUBRC = 4.
    RETURN.
  ENDIF.

  DATA LDF_TIMESTAMP_END TYPE TIMESTAMPL.         "タイムスタンプデータ取得終了
  GET TIME STAMP FIELD LDF_TIMESTAMP_END.         "タイムスタンプデータ取得終了
  DATA(LDF_DATA_COUNT) = LINES( LDT_DATA ).
  IF PIF_ISDISP = ABAP_FALSE.
    CLEAR LDT_DATA.
  ENDIF.
*-----------------------------------------------------------------------
  TRY.
      CL_SALV_TABLE=>FACTORY(
        IMPORTING
          R_SALV_TABLE = DATA(LDO_ALV)
        CHANGING
          T_TABLE      = LDT_DATA ).
    CATCH CX_SALV_MSG INTO DATA(LDX_SALV_MSG).
      POF_SUBRC = 8.
      RETURN.
  ENDTRY.

  DATA(LDO_HEADER) = NEW CL_SALV_FORM_LAYOUT_GRID( ).
  LDO_ALV->SET_TOP_OF_LIST( LDO_HEADER ).
  LDO_HEADER->CREATE_LABEL( ROW = 1 COLUMN = 1 TEXT = 'Performance data' ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 1 TEXT = 'Input records' ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 2 TEXT = 'EKPO' ).
  SELECT FROM EKPO FIELDS COUNT(*) INTO @DATA(LDF_COUNT3).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 3 TEXT = LDF_COUNT3 ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 4 TEXT = 'EKKO' ).
  SELECT FROM EKKO FIELDS COUNT(*) INTO @DATA(LDF_COUNT5).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 5 TEXT = LDF_COUNT5 ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 6 TEXT = 'T001' ).
  SELECT FROM T001 FIELDS COUNT(*) INTO @DATA(LDF_COUNT7).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 7 TEXT = LDF_COUNT7 ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 8 TEXT = 'T024' ).
  SELECT FROM T024 FIELDS COUNT(*) INTO @DATA(LDF_COUNT9).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 9 TEXT = LDF_COUNT9 ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 10 TEXT = 'T024E' ).
  SELECT FROM T024E FIELDS COUNT(*) INTO @DATA(LDF_COUNT11).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 11 TEXT = LDF_COUNT11 ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 12 TEXT = 'T001W' ).
  SELECT FROM T001W FIELDS COUNT(*) INTO @DATA(LDF_COUNT13).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 13 TEXT = LDF_COUNT13 ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 14 TEXT = 'T001L' ).
  SELECT FROM T001L FIELDS COUNT(*) INTO @DATA(LDF_COUNT15).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 15 TEXT = LDF_COUNT15 ).
  LDO_HEADER->CREATE_TEXT( ROW = 3 COLUMN = 1 TEXT = 'Output records' ).
  LDO_HEADER->CREATE_TEXT( ROW = 3 COLUMN = 2 TEXT = LDF_DATA_COUNT ).
  LDO_HEADER->CREATE_TEXT( ROW = 4 COLUMN = 1 TEXT = 'Responce Time [sec]' ).
  LDO_HEADER->CREATE_TEXT( ROW = 4 COLUMN = 2 TEXT = CL_ABAP_TSTMP=>SUBTRACT( TSTMP1 = LDF_TIMESTAMP_END TSTMP2 = LDF_TIMESTAMP_START ) ).

  LDO_ALV->SET_TOP_OF_LIST( LDO_HEADER ).
  LDO_ALV->SET_TOP_OF_LIST_PRINT( LDO_HEADER ).

  LDO_ALV->GET_FUNCTIONS( )->SET_ALL( ).
  LDO_ALV->GET_COLUMNS( )->SET_OPTIMIZE( ).
  LDO_ALV->GET_DISPLAY_SETTINGS( )->SET_STRIPED_PATTERN( ABAP_TRUE ).
  LDO_ALV->GET_SELECTIONS( )->SET_SELECTION_MODE( VALUE = IF_SALV_C_SELECTION_MODE=>CELL ).
  LDO_ALV->DISPLAY( ).

  POF_SUBRC = 0.
ENDFORM.

最近はこんなのを聴いています。
www.youtube.com

検索キーワード
ABAP
ABAP 7.52
SQL
Open SQL
New Open SQL
Classic Open SQL
ABAP SQL
SAP HANA
Code to Data
Code Pushdown
SAP S/4HANA
WITH
SELECT〜FROM @ITAB
FOR ALL ENTRIES IN

以上