ABAP New open SQL:Code Pushdown って何のこと?(2)

ABAP New open SQL:Code Pushdown って何のこと?(2)

何となくシリーズ化しようと思い始めています。
初回は実践とは程遠い要件でしたが、2回目はもう少し実践に近い雰囲気を出してみました。
購買伝票明細一覧を取得します。
伝票番号、伝票タイプ等、組織情報等、数量、明細納入期日の最小および最大を取得します。

N-1
Non-Code Pushdown
ABAP 7.31 OK
従来の実装方法
分納契約納入日程行-明細納入期日の最大値と最小値を取得するのに、
それぞれITABに一旦データを溜め込んで、BINARY SEARCHで取得する
ソースコード:334行
とにかく実装が大変でした。また、データコピーを極力排除したので、従来の実装方法としてこれ以上軽量高速に実装する方法を私は知りません。手前味噌ですが、ほぼチャンピョンデータを叩き出していると思います。(多分)

P-1
Code Pushdown
ABAP 7.31 OK
全てのテーブルを表結合して、明細レコード単位に集約する
ソースコード:99行
今回の実装では、実質最小のコード量です。しかしながら、たまたま要件にフィットしただけの話で、毎回このような実装が取れるわけでは無いです。例えば、特定のルールで分納契約納入日程行の単一レコードを選択してデータを取り出す場合、この方法は取れません。

P-2
Code Pushdown
ABAP 7.52以降
トランザクションデータを全件取得後、
購買伝票ヘッダ、明細データと
分納契約納入日程行-明細納入期日の最大と最小を算出して、
各種マスタデータと表結合する
ソースコード:151行
私が考える、要件に対して柔軟性があり、パフォーマンスも考慮した実装です。私だったら何も指示が無ければこの方法で実装します。

P-3
Code Pushdown
ABAP 7.52以降
分納契約納入日程行-明細納入期日の最大と最小を算出して、
購買伝票ヘッダ、明細データを取得し、
各種マスタデータと表結合する
ソースコード:92行
誤りの例として、実装してみました。EKPOの全てのレコードを取得する場合は要件通り動作しますが、通常は選択画面に入力した値でフィルタすると思います。Where句を充分に効かせることが出来ないのです。少し気を抜くと詳細設計過程で仮実装してしまいます。(今回も気を抜いていました)


パフォーマンスデータ
ABAP 7.52(SAP S/4HANA)HDB環境は以下の通りとなりました。
購買伝票明細:41,000レコード→出力:41,000レコード
分納契約納入日程行は、明細1レコードに対してほぼ1レコードなので、レコード集約は僅かに行われる程度となっています。SAP HANAは集約が非常に速く、集約度合いが増すとパフォーマンス差が大きくなります。

N-1:0.69sec
P-1:0.72sec
P-2:0.45sec
P-3:0.66sec
結果としては、P-2:Code Pushdownの私が考える実装方法がトップタイムを叩き出して、一先ず安心しました。個人的に意外だったのは、N-1:Non-Code Pushdownが大健闘だったことです。BINARY SEARCHを充分に効かせて、フィールドシンボルでデータコピーを最小限にすると、データ量によっては、まだまだパフォーマンスを充分確保することが出来ると思いました。ただし、…実装するのに骨が折れそうになります。辛い…。

ABAP 7.31(ERP 6.0)Oracle10.2環境は以下の通りとなりました。
購買伝票明細:31,000レコード→出力:31,000レコード

N-1:1.55
初回は20-30秒

P-1:0.34
初回は0.8-1.0秒

何故か、この環境は初回と2回目以降で、パフォーマンス差が大きかったので、初回データも載せました。私はABAPのバッファアクセスについてよく知らないのですが、おそらく2回目以降はバッファアクセスが十分に効いているのだと思います。ただし、JOIN句を使用すると確かバッファアクセスは無効になるんでしたっけ?知識不足でごめんなさい。そうは言ってもP-1:Code Pushdownの圧勝でした。特に初回アクセスでは大差がつきました。データベースの並列実行に対するパフォーマンス悪化はあるのかもしれませんが、比較的モダンなOracle10.2です。多分しんこくなじたいにはならないのではないかとおもいます。無責任ですが…。

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

*&---------------------------------------------------------------------*
*& Report  Y_SQL_CONSOLE
*&---------------------------------------------------------------------*
REPORT Y_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_731N1 RADIOBUTTON GROUP RB1,                 "N-1:Non-Code Pushdown:ITABを活用した従来の実装方法
  P_731P1 RADIOBUTTON GROUP RB1,                 "P-1:Code Pushdown:全てのテーブルを表結合して、明細レコード単位に集約する
  P_740P2 RADIOBUTTON GROUP RB1,                 "P-2:Code Pushdown:トランザクションデータを全件取得後、ヘッダ明細、分納契約納入日程行に分けて、最後に各種マスタデータと表結合する
  P_740P3 RADIOBUTTON GROUP RB1.                 "P-3:Code Pushdown:分納契約納入日程行を取得して、ヘッダ明細を取得し、最後に各種マスタデータと表結合する

*-----------------------------------------------------------------------
* START-OF-SELECTION
*-----------------------------------------------------------------------
START-OF-SELECTION.
  CASE ABAP_TRUE.
    WHEN P_731N1.
      PERFORM START_OF_SELECTION_731N1
        USING
          P_ISDISP                                "表示フラグ
          P_TBMAXS                                "選択するエントリの最大数
        CHANGING
          GDS_BAPIRET2                            "リターンパラメータ
          GDF_SUBRC.                              "リターンコード
      IF GDF_SUBRC <> 0.                          "リターンコード
        LEAVE TO LIST-PROCESSING.
      ENDIF.
    WHEN P_731P1.
      PERFORM START_OF_SELECTION_731P1
        USING
          P_ISDISP                                "表示フラグ
          P_TBMAXS                                "選択するエントリの最大数
        CHANGING
          GDS_BAPIRET2                            "リターンパラメータ
          GDF_SUBRC.                              "リターンコード
      IF GDF_SUBRC <> 0.                          "リターンコード
        LEAVE TO LIST-PROCESSING.
      ENDIF.
    WHEN P_740P2.
      PERFORM START_OF_SELECTION_740P2
        USING
          P_ISDISP                                "表示フラグ
          P_TBMAXS                                "選択するエントリの最大数
        CHANGING
          GDS_BAPIRET2                            "リターンパラメータ
          GDF_SUBRC.                              "リターンコード
      IF GDF_SUBRC <> 0.                          "リターンコード
        LEAVE TO LIST-PROCESSING.
      ENDIF.
    WHEN P_740P3.
      PERFORM START_OF_SELECTION_740P3
        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_731N1
    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,                 "購買伝票の明細番号
      BSART      TYPE EKKO-BSART,                 "購買伝票タイプ
      EKKO_LOEKZ TYPE EKKO-LOEKZ,                 "購買伝票の削除フラグ:ヘッダ
      PSTYP      TYPE EKPO-PSTYP,                 "購買伝票の明細カテゴリ
      EKPO_LOEKZ TYPE EKPO-LOEKZ,                 "購買伝票の削除フラグ:明細
      BUKRS      TYPE EKKO-BUKRS,                 "会社コード
      BUTXT      TYPE T001-BUTXT,                 "会社コードまたは会社の名称
      EKGRP      TYPE EKKO-EKGRP,                 "購買グループ
      EKNAM      TYPE T024-EKNAM,                 "購買グループテキスト
      EKORG      TYPE EKKO-EKORG,                 "購買組織
      EKOTX      TYPE T024E-EKOTX,                "購買組織テキスト
      WERKS      TYPE EKPO-WERKS,                 "プラント
      NAME1      TYPE T001W-NAME1,                "名称
      LGORT      TYPE EKPO-LGORT,                 "保管場所
      LGOBE      TYPE T001L-LGOBE,                "保管場所テキスト
      MATNR      TYPE EKPO-MATNR,                 "品目コード
      TXZ01      TYPE EKPO-TXZ01,                 "テキスト (短)
      MENGE      TYPE EKPO-MENGE,                 "購買発注量
      MEINS      TYPE EKPO-MEINS,                 "発注単位
      EINDT_MIN  TYPE EKET-EINDT,                 "明細納入期日:最小
      EINDT_MAX  TYPE EKET-EINDT,                 "明細納入期日:最大
    END OF LTS_DATA,
    LTT_DATA TYPE STANDARD TABLE OF LTS_DATA,     "一覧データ


    BEGIN OF LTS_EKET,
      EBELN TYPE EKPO-EBELN,                      "購買伝票番号
      EBELP TYPE EKPO-EBELP,                      "購買伝票の明細番号
      EINDT TYPE EKET-EINDT,                      "明細納入期日
    END OF LTS_EKET,
    LTT_EKET TYPE STANDARD TABLE OF LTS_EKET,


    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_T024,                            "購買グループ
      EKGRP TYPE T024-EKGRP,                      "購買グループ
      EKNAM TYPE T024-EKNAM,                      "購買グループテキスト
    END OF LTS_T024,
    LTT_T024 TYPE STANDARD TABLE OF LTS_T024,     "購買グループ

    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_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_EKET_MIN TYPE LTT_EKET,                   "分納契約納入日程行:最小
    LDT_EKET_MAX TYPE LTT_EKET,                   "分納契約納入日程行:最大

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

  FIELD-SYMBOLS:
    <LFS_DATA>     LIKE LINE OF LDT_DATA,         "一覧データ

    <LFS_EKET_MIN> LIKE LINE OF LDT_EKET_MIN,     "分納契約納入日程行:最小
    <LFS_EKET_MAX> LIKE LINE OF LDT_EKET_MAX,     "分納契約納入日程行:最大

    <LFS_T001>     LIKE LINE OF LDT_T001,         "会社コード
    <LFS_T024>     LIKE LINE OF LDT_T024,         "購買グループ
    <LFS_T024E>    LIKE LINE OF LDT_T024E,        "購買組織
    <LFS_T001W>    LIKE LINE OF LDT_T001W,        "プラント/支店
    <LFS_T001L>    LIKE LINE OF LDT_T001L.        "保管場所

  SELECT
      EKPO~EBELN                                  "購買伝票番号
      EKPO~EBELP                                  "購買伝票の明細番号
      EKKO~BSART                                  "購買伝票タイプ
      EKKO~LOEKZ AS EKKO_LOEKZ                    "購買伝票の削除フラグ:ヘッダ
      EKPO~PSTYP                                  "購買伝票の明細カテゴリ
      EKPO~LOEKZ AS EKPO_LOEKZ                    "購買伝票の削除フラグ:明細
      EKKO~BUKRS                                  "会社コード
      EKKO~EKGRP                                  "購買グループ
      EKKO~EKORG                                  "購買組織
      EKPO~WERKS                                  "プラント
      EKPO~LGORT                                  "保管場所
      EKPO~MATNR                                  "品目コード
      EKPO~TXZ01                                  "テキスト (短)
      EKPO~MENGE                                  "購買発注量
      EKPO~MEINS                                  "発注単位
    INTO CORRESPONDING FIELDS OF TABLE LDT_DATA
    FROM EKPO                                     "購買伝票明細
    INNER JOIN EKKO                               "購買伝票ヘッダ
       ON EKKO~EBELN = EKPO~EBELN.                "購買伝票番号
  SORT LDT_DATA ASCENDING BY
      EBELN                                       "購買伝票番号
      EBELP.                                      "購買伝票の明細番号

  IF LDT_DATA IS NOT INITIAL.                     "一覧データ
    SELECT
        EKET~EBELN                                "購買伝票番号
        EKET~EBELP                                "購買伝票の明細番号
        EKET~EINDT                                "明細納入期日
      INTO TABLE LDT_EKET_MIN                     "分納契約納入日程行:最小
      FROM EKET                                   "分納契約納入日程行
      FOR ALL ENTRIES IN LDT_DATA                 "一覧データ
      WHERE EKET~EBELN = LDT_DATA-EBELN           "購買伝票番号
        AND EKET~EBELP = LDT_DATA-EBELP.          "購買伝票の明細番号
    IF SY-SUBRC = 0.
      LDT_EKET_MAX[] = LDT_EKET_MIN[].            "分納契約納入日程行:最大
      SORT LDT_EKET_MIN BY                        "分納契約納入日程行:最小
          EBELN ASCENDING                         "購買伝票番号
          EBELP ASCENDING                         "購買伝票の明細番号
          EINDT ASCENDING.                        "明細納入期日
      DELETE ADJACENT DUPLICATES FROM LDT_EKET_MIN COMPARING"分納契約納入日程行:最小
          EBELN                                   "購買伝票番号
          EBELP.                                  "購買伝票の明細番号
      SORT LDT_EKET_MAX BY                        "分納契約納入日程行:最大
          EBELN ASCENDING                         "購買伝票番号
          EBELP ASCENDING                         "購買伝票の明細番号
          EINDT DESCENDING.                       "明細納入期日
      DELETE ADJACENT DUPLICATES FROM LDT_EKET_MAX COMPARING"分納契約納入日程行:最大
          EBELN                                   "購買伝票番号
          EBELP.                                  "購買伝票の明細番号
    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                                "会社コードまたは会社の名称
      INTO TABLE LDT_T001                         "会社コード
      FROM T001
      FOR ALL ENTRIES IN LDT_DATA1                "一覧データ:作業用
      WHERE T001~BUKRS = LDT_DATA1-BUKRS.         "会社コード
    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                     "一覧データ:作業用
      EKGRP.
  DELETE ADJACENT DUPLICATES FROM LDT_DATA1 COMPARING"一覧データ:作業用
      EKGRP.
  IF LDT_DATA1 IS NOT INITIAL.                    "一覧データ:作業用
    SELECT
        T024~EKGRP                                "購買グループ
        T024~EKNAM                                "購買グループテキスト
      INTO TABLE LDT_T024                         "購買グループ
      FROM T024                                   "購買グループ
      FOR ALL ENTRIES IN LDT_DATA1                "一覧データ:作業用
      WHERE T024~EKGRP = LDT_DATA1-EKGRP.         "購買グループ
    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                     "一覧データ:作業用
      EKORG.                                      "購買組織
  DELETE ADJACENT DUPLICATES FROM LDT_DATA1 COMPARING"一覧データ:作業用
      EKORG.                                      "購買組織
  IF LDT_DATA1 IS NOT INITIAL.                    "一覧データ:作業用
    SELECT
        T024E~EKORG                               "購買組織
        T024E~EKOTX                               "購買組織テキスト
      INTO TABLE LDT_T024E                        "購買組織
      FROM T024E                                  "購買組織
      FOR ALL ENTRIES IN LDT_DATA1                "一覧データ:作業用
      WHERE T024E~EKORG = LDT_DATA1-EKORG.        "購買組織
    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                     "一覧データ:作業用
      WERKS.
  DELETE ADJACENT DUPLICATES FROM LDT_DATA1 COMPARING"一覧データ:作業用
      WERKS.
  IF LDT_DATA1 IS NOT INITIAL.                    "一覧データ:作業用
    SELECT
        T001W~WERKS                               "プラント
        T001W~NAME1                               "名称
      INTO TABLE LDT_T001W                        "プラント/支店
      FROM T001W                                  "プラント/支店
      FOR ALL ENTRIES IN LDT_DATA1                "一覧データ:作業用
      WHERE T001W~WERKS = LDT_DATA1-WERKS.        "プラント
    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                               "保管場所テキスト
      INTO TABLE LDT_T001L                        "保管場所
      FROM T001L                                  "保管場所
      FOR ALL ENTRIES IN LDT_DATA1                "一覧データ:作業用
      WHERE T001L~WERKS = LDT_DATA1-WERKS         "プラント
        AND T001L~LGORT = LDT_DATA1-LGORT.        "保管場所
    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 <LFS_DATA>.          "一覧データ

    READ TABLE LDT_EKET_MIN WITH KEY              "分納契約納入日程行:最小
        EBELN = <LFS_DATA>-EBELN                  "購買伝票番号
        EBELP = <LFS_DATA>-EBELP                  "購買伝票の明細番号
      BINARY SEARCH
      ASSIGNING <LFS_EKET_MIN>.                   "分納契約納入日程行:最小
    IF SY-SUBRC = 0.
      <LFS_DATA>-EINDT_MIN = <LFS_EKET_MIN>-EINDT."明細納入期日:最小
    ENDIF.

    READ TABLE LDT_EKET_MAX                       "分納契約納入日程行:最大
      WITH KEY
        EBELN = <LFS_DATA>-EBELN                  "購買伝票番号
        EBELP = <LFS_DATA>-EBELP                  "購買伝票の明細番号
      BINARY SEARCH
      ASSIGNING <LFS_EKET_MAX>.                   "分納契約納入日程行:最大
    IF SY-SUBRC = 0.
      <LFS_DATA>-EINDT_MAX = <LFS_EKET_MAX>-EINDT."明細納入期日:最大
    ENDIF.

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

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

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

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

    READ TABLE LDT_T001L WITH KEY                 "保管場所
        WERKS = <LFS_DATA>-WERKS                  "プラント
        LGORT = <LFS_DATA>-LGORT                  "保管場所
      BINARY SEARCH
      ASSIGNING <LFS_T001L>.                      "保管場所
    IF SY-SUBRC = 0.
      <LFS_DATA>-LGOBE = <LFS_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 = 'EKET' ).
  SELECT FROM EKET 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 = 'T001' ).
  SELECT FROM T001 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 = 'T024' ).
  SELECT FROM T024 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 = 'T024E' ).
  SELECT FROM T024E 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 = 'T001W' ).
  SELECT FROM T001W FIELDS COUNT(*) INTO @DATA(LDF_COUNT15).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 15 TEXT = LDF_COUNT15 ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 16 TEXT = 'T001L' ).
  SELECT FROM T001L FIELDS COUNT(*) INTO @DATA(LDF_COUNT17).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 17 TEXT = LDF_COUNT17 ).
  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_731P1
    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,                 "購買伝票の明細番号
      BSART      TYPE EKKO-BSART,                 "購買伝票タイプ
      EKKO_LOEKZ TYPE EKKO-LOEKZ,                 "購買伝票の削除フラグ:ヘッダ
      PSTYP      TYPE EKPO-PSTYP,                 "購買伝票の明細カテゴリ
      EKPO_LOEKZ TYPE EKPO-LOEKZ,                 "購買伝票の削除フラグ:明細
      BUKRS      TYPE EKKO-BUKRS,                 "会社コード
      BUTXT      TYPE T001-BUTXT,                 "会社コードまたは会社の名称
      EKGRP      TYPE EKKO-EKGRP,                 "購買グループ
      EKNAM      TYPE T024-EKNAM,                 "購買グループテキスト
      EKORG      TYPE EKKO-EKORG,                 "購買組織
      EKOTX      TYPE T024E-EKOTX,                "購買組織テキスト
      WERKS      TYPE EKPO-WERKS,                 "プラント
      NAME1      TYPE T001W-NAME1,                "名称
      LGORT      TYPE EKPO-LGORT,                 "保管場所
      LGOBE      TYPE T001L-LGOBE,                "保管場所テキスト
      MATNR      TYPE EKPO-MATNR,                 "品目コード
      TXZ01      TYPE EKPO-TXZ01,                 "テキスト (短)
      MENGE      TYPE EKPO-MENGE,                 "購買発注量
      MEINS      TYPE EKPO-MEINS,                 "発注単位
      EINDT_MIN  TYPE EKET-EINDT,                 "明細納入期日:最小
      EINDT_MAX  TYPE EKET-EINDT,                 "明細納入期日:最大
    END OF LTS_DATA,
    LTT_DATA TYPE STANDARD TABLE OF LTS_DATA.

  DATA:
    LDT_DATA TYPE LTT_DATA.

  SELECT
      EKPO~EBELN                                  "購買伝票番号
      EKPO~EBELP                                  "購買伝票の明細番号
      EKKO~BSART                                  "購買伝票タイプ
      EKKO~LOEKZ AS EKKO_LOEKZ                    "購買伝票の削除フラグ:ヘッダ
      EKPO~PSTYP                                  "購買伝票の明細カテゴリ
      EKPO~LOEKZ AS EKPO_LOEKZ                    "購買伝票の削除フラグ:明細
      EKKO~BUKRS                                  "会社コード
      T001~BUTXT                                  "会社コードまたは会社の名称
      EKKO~EKGRP                                  "購買グループ
      T024~EKNAM                                  "購買グループテキスト
      EKKO~EKORG                                  "購買組織
      T024E~EKOTX                                 "購買組織テキスト
      EKPO~WERKS                                  "プラント
      T001W~NAME1                                 "名称
      EKPO~LGORT                                  "保管場所
      T001L~LGOBE                                 "保管場所テキスト
      EKPO~MATNR                                  "品目コード
      EKPO~TXZ01                                  "テキスト (短)
      EKPO~MENGE                                  "購買発注量
      EKPO~MEINS                                  "発注単位
      MIN( EKET~EINDT ) AS EINDT_MIN              "明細納入期日:最小
      MAX( EKET~EINDT ) AS EINDT_MAX              "明細納入期日:最大
    INTO TABLE LDT_DATA
    FROM EKPO                                     "購買伝票明細
    INNER JOIN EKKO                               "購買伝票ヘッダ
       ON EKKO~EBELN = EKPO~EBELN                 "購買伝票番号
    LEFT OUTER JOIN EKET                          "分納契約納入日程行
       ON EKET~EBELN = EKPO~EBELN                 "購買伝票番号
      AND EKET~EBELP = EKPO~EBELP                 "購買伝票の明細番号
    LEFT OUTER JOIN T001                          "会社コード
       ON T001~BUKRS = EKKO~BUKRS                 "会社コード
    LEFT OUTER JOIN T024                          "購買グループ
       ON T024~EKGRP = EKKO~EKGRP                 "購買グループ
    LEFT OUTER JOIN T024E                         "購買組織
       ON T024E~EKORG = EKKO~EKORG                "購買組織
    LEFT OUTER JOIN T001W                         "プラント/支店
       ON T001W~WERKS = EKPO~WERKS                "プラント
    LEFT OUTER JOIN T001L                         "保管場所
       ON T001L~WERKS = EKPO~WERKS                "プラント
      AND T001L~LGORT = EKPO~LGORT                "保管場所
    GROUP BY
      EKPO~EBELN                                  "購買伝票番号
      EKPO~EBELP                                  "購買伝票の明細番号
      EKKO~BSART                                  "購買伝票タイプ
      EKKO~LOEKZ                                  "購買伝票の削除フラグ:ヘッダ
      EKPO~PSTYP                                  "購買伝票の明細カテゴリ
      EKPO~LOEKZ                                  "購買伝票の削除フラグ:明細
      EKKO~BUKRS                                  "会社コード
      T001~BUTXT                                  "会社コードまたは会社の名称
      EKKO~EKGRP                                  "購買グループ
      T024~EKNAM                                  "購買グループテキスト
      EKKO~EKORG                                  "購買組織
      T024E~EKOTX                                 "購買組織テキスト
      EKPO~WERKS                                  "プラント
      T001W~NAME1                                 "名称
      EKPO~LGORT                                  "保管場所
      T001L~LGOBE                                 "保管場所テキスト
      EKPO~MATNR                                  "品目コード
      EKPO~TXZ01                                  "テキスト (短)
      EKPO~MENGE                                  "購買発注量
      EKPO~MEINS                                  "発注単位
    ORDER BY
      EKPO~EBELN                                  "購買伝票番号
      EKPO~EBELP.                                 "購買伝票の明細番号

  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 = 'EKET' ).
  SELECT FROM EKET 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 = 'T001' ).
  SELECT FROM T001 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 = 'T024' ).
  SELECT FROM T024 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 = 'T024E' ).
  SELECT FROM T024E 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 = 'T001W' ).
  SELECT FROM T001W FIELDS COUNT(*) INTO @DATA(LDF_COUNT15).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 15 TEXT = LDF_COUNT15 ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 16 TEXT = 'T001L' ).
  SELECT FROM T001L FIELDS COUNT(*) INTO @DATA(LDF_COUNT17).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 17 TEXT = LDF_COUNT17 ).
  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_740P2
    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,                 "購買伝票の明細番号
      BSART      TYPE EKKO-BSART,                 "購買伝票タイプ
      EKKO_LOEKZ TYPE EKKO-LOEKZ,                 "購買伝票の削除フラグ:ヘッダ
      PSTYP      TYPE EKPO-PSTYP,                 "購買伝票の明細カテゴリ
      EKPO_LOEKZ TYPE EKPO-LOEKZ,                 "購買伝票の削除フラグ:明細
      BUKRS      TYPE EKKO-BUKRS,                 "会社コード
      BUTXT      TYPE T001-BUTXT,                 "会社コードまたは会社の名称
      EKGRP      TYPE EKKO-EKGRP,                 "購買グループ
      EKNAM      TYPE T024-EKNAM,                 "購買グループテキスト
      EKORG      TYPE EKKO-EKORG,                 "購買組織
      EKOTX      TYPE T024E-EKOTX,                "購買組織テキスト
      WERKS      TYPE EKPO-WERKS,                 "プラント
      NAME1      TYPE T001W-NAME1,                "名称
      LGORT      TYPE EKPO-LGORT,                 "保管場所
      LGOBE      TYPE T001L-LGOBE,                "保管場所テキスト
      MATNR      TYPE EKPO-MATNR,                 "品目コード
      TXZ01      TYPE EKPO-TXZ01,                 "テキスト (短)
      MENGE      TYPE EKPO-MENGE,                 "購買発注量
      MEINS      TYPE EKPO-MEINS,                 "発注単位
      EINDT_MIN  TYPE EKET-EINDT,                 "明細納入期日:最小
      EINDT_MAX  TYPE EKET-EINDT,                 "明細納入期日:最大
    END OF LTS_DATA,
    LTT_DATA TYPE STANDARD TABLE OF LTS_DATA.

  DATA:
    LDT_DATA TYPE LTT_DATA.

  WITH
  +EKXX AS (                                      "購買伝票
  SELECT
      EKPO~EBELN,                                 "購買伝票番号
      EKPO~EBELP,                                 "購買伝票の明細番号
      EKKO~BSART,                                 "購買伝票タイプ
      EKKO~LOEKZ AS EKKO_LOEKZ,                   "購買伝票の削除フラグ:ヘッダ
      EKPO~PSTYP,                                 "購買伝票の明細カテゴリ
      EKPO~LOEKZ AS EKPO_LOEKZ,                   "購買伝票の削除フラグ:明細
      EKKO~BUKRS,                                 "会社コード
      EKKO~EKGRP,                                 "購買グループ
      EKKO~EKORG,                                 "購買組織
      EKPO~WERKS,                                 "プラント
      EKPO~LGORT,                                 "保管場所
      EKPO~MATNR,                                 "品目コード
      EKPO~TXZ01,                                 "テキスト (短)
      EKPO~MENGE,                                 "購買発注量
      EKPO~MEINS,                                 "発注単位
      EKET~EINDT                                  "明細納入期日
    FROM EKPO                                     "購買伝票明細
    INNER JOIN EKKO                               "購買伝票ヘッダ
       ON EKKO~EBELN = EKPO~EBELN                 "購買伝票番号
    LEFT OUTER JOIN EKET                          "分納契約納入日程行
       ON EKET~EBELN = EKPO~EBELN                 "購買伝票番号
      AND EKET~EBELP = EKPO~EBELP                 "購買伝票の明細番号
  ),
  +EKPO AS (                                      "購買伝票明細
  SELECT
      +EKXX~EBELN,                                "購買伝票番号
      +EKXX~EBELP,                                "購買伝票の明細番号
      +EKXX~BSART,                                "購買伝票タイプ
      +EKXX~EKKO_LOEKZ,                           "購買伝票の削除フラグ:ヘッダ
      +EKXX~PSTYP,                                "購買伝票の明細カテゴリ
      +EKXX~EKPO_LOEKZ,                           "購買伝票の削除フラグ:明細
      +EKXX~BUKRS,                                "会社コード
      +EKXX~EKGRP,                                "購買グループ
      +EKXX~EKORG,                                "購買組織
      +EKXX~WERKS,                                "プラント
      +EKXX~LGORT,                                "保管場所
      +EKXX~MATNR,                                "品目コード
      +EKXX~TXZ01,                                "テキスト (短)
      +EKXX~MENGE,                                "購買発注量
      +EKXX~MEINS                                 "発注単位
    FROM +EKXX                                    "購買伝票
    GROUP BY
      +EKXX~EBELN,                                "購買伝票番号
      +EKXX~EBELP,                                "購買伝票の明細番号
      +EKXX~BSART,                                "購買伝票タイプ
      +EKXX~EKKO_LOEKZ,                           "購買伝票の削除フラグ:ヘッダ
      +EKXX~PSTYP,                                "購買伝票の明細カテゴリ
      +EKXX~EKPO_LOEKZ,                           "購買伝票の削除フラグ:明細
      +EKXX~BUKRS,                                "会社コード
      +EKXX~EKGRP,                                "購買グループ
      +EKXX~EKORG,                                "購買組織
      +EKXX~WERKS,                                "プラント
      +EKXX~LGORT,                                "保管場所
      +EKXX~MATNR,                                "品目コード
      +EKXX~TXZ01,                                "テキスト (短)
      +EKXX~MENGE,                                "購買発注量
      +EKXX~MEINS                                 "発注単位
  ),
  +EKET AS (                                      "分納契約納入日程行
  SELECT
      +EKXX~EBELN,                                "購買伝票番号
      +EKXX~EBELP,                                "購買伝票の明細番号
      MIN( +EKXX~EINDT ) AS EINDT_MIN,            "明細納入期日:最小
      MAX( +EKXX~EINDT ) AS EINDT_MAX             "明細納入期日:最大
    FROM +EKXX                                    "購買伝票
    GROUP BY
      +EKXX~EBELN,                                "購買伝票番号
      +EKXX~EBELP                                 "購買伝票の明細番号
  )
  SELECT
      +EKPO~EBELN,                                "購買伝票番号
      +EKPO~EBELP,                                "購買伝票の明細番号
      +EKPO~BSART,                                "購買伝票タイプ
      +EKPO~EKKO_LOEKZ,                           "購買伝票の削除フラグ:ヘッダ
      +EKPO~PSTYP,                                "購買伝票の明細カテゴリ
      +EKPO~EKPO_LOEKZ,                           "購買伝票の削除フラグ:明細
      +EKPO~BUKRS,                                "会社コード
      T001~BUTXT,                                 "会社コードまたは会社の名称
      +EKPO~EKGRP,                                "購買グループ
      T024~EKNAM,                                 "購買グループテキスト
      +EKPO~EKORG,                                "購買組織
      T024E~EKOTX,                                "購買組織テキスト
      +EKPO~WERKS,                                "プラント
      T001W~NAME1,                                "名称
      +EKPO~LGORT,                                "保管場所
      T001L~LGOBE,                                "保管場所テキスト
      +EKPO~MATNR,                                "品目コード
      +EKPO~TXZ01,                                "テキスト (短)
      +EKPO~MENGE,                                "購買発注量
      +EKPO~MEINS,                                "発注単位
      +EKET~EINDT_MIN,                            "明細納入期日:最小
      +EKET~EINDT_MAX                             "明細納入期日:最大
    FROM +EKPO                                    "購買伝票明細
    LEFT OUTER JOIN +EKET                         "分納契約納入日程行
       ON +EKET~EBELN = +EKPO~EBELN               "購買伝票番号
      AND +EKET~EBELP = +EKPO~EBELP               "購買伝票の明細番号
    LEFT OUTER JOIN T001                          "会社コード
       ON T001~BUKRS = +EKPO~BUKRS                "会社コード
    LEFT OUTER JOIN T024                          "購買グループ
       ON T024~EKGRP = +EKPO~EKGRP                "購買グループ
    LEFT OUTER JOIN T024E                         "購買組織
       ON T024E~EKORG = +EKPO~EKORG               "購買組織
    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.

  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 = 'EKET' ).
  SELECT FROM EKET 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 = 'T001' ).
  SELECT FROM T001 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 = 'T024' ).
  SELECT FROM T024 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 = 'T024E' ).
  SELECT FROM T024E 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 = 'T001W' ).
  SELECT FROM T001W FIELDS COUNT(*) INTO @DATA(LDF_COUNT15).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 15 TEXT = LDF_COUNT15 ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 16 TEXT = 'T001L' ).
  SELECT FROM T001L FIELDS COUNT(*) INTO @DATA(LDF_COUNT17).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 17 TEXT = LDF_COUNT17 ).
  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_740P3
    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,                 "購買伝票の明細番号
      BSART      TYPE EKKO-BSART,                 "購買伝票タイプ
      EKKO_LOEKZ TYPE EKKO-LOEKZ,                 "購買伝票の削除フラグ:ヘッダ
      PSTYP      TYPE EKPO-PSTYP,                 "購買伝票の明細カテゴリ
      EKPO_LOEKZ TYPE EKPO-LOEKZ,                 "購買伝票の削除フラグ:明細
      BUKRS      TYPE EKKO-BUKRS,                 "会社コード
      BUTXT      TYPE T001-BUTXT,                 "会社コードまたは会社の名称
      EKGRP      TYPE EKKO-EKGRP,                 "購買グループ
      EKNAM      TYPE T024-EKNAM,                 "購買グループテキスト
      EKORG      TYPE EKKO-EKORG,                 "購買組織
      EKOTX      TYPE T024E-EKOTX,                "購買組織テキスト
      WERKS      TYPE EKPO-WERKS,                 "プラント
      NAME1      TYPE T001W-NAME1,                "名称
      LGORT      TYPE EKPO-LGORT,                 "保管場所
      LGOBE      TYPE T001L-LGOBE,                "保管場所テキスト
      MATNR      TYPE EKPO-MATNR,                 "品目コード
      TXZ01      TYPE EKPO-TXZ01,                 "テキスト (短)
      MENGE      TYPE EKPO-MENGE,                 "購買発注量
      MEINS      TYPE EKPO-MEINS,                 "発注単位
      EINDT_MIN  TYPE EKET-EINDT,                 "明細納入期日:最小
      EINDT_MAX  TYPE EKET-EINDT,                 "明細納入期日:最大
    END OF LTS_DATA,
    LTT_DATA TYPE STANDARD TABLE OF LTS_DATA.

  DATA:
    LDT_DATA TYPE LTT_DATA.

  WITH
  +EKET AS (                                      "分納契約納入日程行
  SELECT
      EKET~EBELN,                                 "購買伝票番号
      EKET~EBELP,                                 "購買伝票の明細番号
      MIN( EKET~EINDT ) AS EINDT_MIN,             "明細納入期日:最小
      MAX( EKET~EINDT ) AS EINDT_MAX              "明細納入期日:最大
    FROM EKET                                     "分納契約納入日程行
    GROUP BY
      EKET~EBELN,                                 "購買伝票番号
      EKET~EBELP                                  "購買伝票の明細番号
     )
  SELECT
      EKPO~EBELN,                                 "購買伝票番号
      EKPO~EBELP,                                 "購買伝票の明細番号
      EKKO~BSART,                                 "購買伝票タイプ
      EKKO~LOEKZ AS EKKO_LOEKZ,                   "購買伝票の削除フラグ:ヘッダ
      EKPO~PSTYP,                                 "購買伝票の明細カテゴリ
      EKPO~LOEKZ AS EKPO_LOEKZ,                   "購買伝票の削除フラグ:明細
      EKKO~BUKRS,                                 "会社コード
      T001~BUTXT,                                 "会社コードまたは会社の名称
      EKKO~EKGRP,                                 "購買グループ
      T024~EKNAM,                                 "購買グループテキスト
      EKKO~EKORG,                                 "購買組織
      T024E~EKOTX,                                "購買組織テキスト
      EKPO~WERKS,                                 "プラント
      T001W~NAME1,                                "名称
      EKPO~LGORT,                                 "保管場所
      T001L~LGOBE,                                "保管場所テキスト
      EKPO~MATNR,                                 "品目コード
      EKPO~TXZ01,                                 "テキスト (短)
      EKPO~MENGE,                                 "購買発注量
      EKPO~MEINS,                                 "発注単位
      +EKET~EINDT_MIN,                            "明細納入期日:最小
      +EKET~EINDT_MAX                             "明細納入期日:最大
    FROM EKPO                                     "購買伝票明細
    INNER JOIN EKKO                               "購買伝票ヘッダ
       ON EKKO~EBELN = EKPO~EBELN                 "購買伝票番号
    LEFT OUTER JOIN +EKET                         "分納契約納入日程行
       ON +EKET~EBELN = EKPO~EBELN                "購買伝票番号
      AND +EKET~EBELP = EKPO~EBELP                "購買伝票の明細番号
    LEFT OUTER JOIN T001                          "会社コード
       ON T001~BUKRS = EKKO~BUKRS                 "会社コード
    LEFT OUTER JOIN T024                          "購買グループ
       ON T024~EKGRP = EKKO~EKGRP                 "購買グループ
    LEFT OUTER JOIN T024E                         "購買組織
       ON T024E~EKORG = EKKO~EKORG                "購買組織
    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.

  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 = 'EKET' ).
  SELECT FROM EKET 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 = 'T001' ).
  SELECT FROM T001 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 = 'T024' ).
  SELECT FROM T024 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 = 'T024E' ).
  SELECT FROM T024E 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 = 'T001W' ).
  SELECT FROM T001W FIELDS COUNT(*) INTO @DATA(LDF_COUNT15).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 15 TEXT = LDF_COUNT15 ).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 16 TEXT = 'T001L' ).
  SELECT FROM T001L FIELDS COUNT(*) INTO @DATA(LDF_COUNT17).
  LDO_HEADER->CREATE_TEXT( ROW = 2 COLUMN = 17 TEXT = LDF_COUNT17 ).
  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.

検索キーワード
ABAP
ABAP 7.31
ABAP 7.4
ABAP 7.50
ABAP 7.51
ABAP 7.52
SQL
Open SQL
New Open SQL
Classic Open SQL
ABAP SQL
SAP HANA
Code to Data
Code Pushdown
SAP ERP 6.0
SAP S/4HANA
SELECT
JOIN
INNER JOIN
OUTER JOIN
LEFT OUTER JOIN
GROUP BY
ORDER BY