ABAP SQL でのコードプッシュダウンの使用

ABAP SQL での計算および文字列処理の実行

Objectives

After completing this lesson, you will be able to:
  • データベースで計算を実行します。
  • データベースで文字列処理を実行します。

算術式

ABAP SQL では、算術式を項目一覧のエレメントとして使用することができます。

ABAP SQL では、4 つの基本演算子、括弧、および 3 つの異なる算数 (整数、小数、浮動小数点) がサポートされています。中間結果の値の範囲と精度は、使用される算術式に大きく依存します。

算術演算は、式で使用されるオペランドから導出されます。

  • 式に整数オペランドのみが含まれている場合、式は整数式であり、結果も整数型です。
  • 式に小数データ型のオペランド (ディクショナリデータ型 DEC、QUAN、CURR、ABAP データ型 p) が含まれていると、式の結果はデータ型 DEC になります。
  • すべてのオペランドにバイナリ浮動小数点型 (ディクショナリデータ型 FLTP、ABAP データ型 f) がある場合、式は浮動小数点式であり、結果は FLTP 型です。

以下の重要な制約があります。

  • 除算演算子 (/) は浮動小数点式でのみ使用できます。
  • 浮動小数点型と他の数値型を同じ式で使用することはできません。

ヒント

CAST( ) を使用してデータ型を FLTP に変換することにより、浮動小数点式で任意の数値オペランドを使用することができます。

例: ABAP SQL における算術式

この例では、ABAP SQL SELECT 命令の項目一覧における算術式の 2 つの例を示しています。

項目 SEATS_AVAILABLE は、予約済座席数 (テーブル項目 SEATS_OCCUPIED) をそのフライトの全座席数 (テーブル項目 SEATS_MAX) から差し引いて計算されます。どちらのオペランドも整数型であるため、この式の結果も整数になります。

項目 PERCENTAGE_FLTP では、予約済席の割合が 0 から 100 までの数値で計算されます。このためには、予約済座席数をリテラル 100 で乗算し、結果を全体的な座席数で除算する必要があります。除算演算子は浮動小数点式でのみ使用可能であるため、すべてのオペランドをデータ型 FLTP に変換する必要があります。その結果、結果のタイプも FLTP になり、デフォルトで科学表記で表示されます。

注記

数値リテラル 100 は整数型であるため、FLTP 型にも変換する必要があります。または、値 100.0 で f 型の定数を定義し、この定数を SQL 式で使用することもできます。

試してみる: 算術式

  1. インタフェース IF_OO_ADT_CLASSRUN を実装する新しいグローバルクラスを登録します。
  2. 以下のコードスニペットをメソッド if_oo_adt_classrun~main( ) の実装部分にコピーします。
    Code Snippet
    1234567891011121314151617181920
    SELECT FROM /dmo/flight FIELDS seats_max, seats_occupied, seats_max - seats_occupied AS seats_avaliable, ( CAST( seats_occupied AS FLTP ) * CAST( 100 AS FLTP ) ) / CAST( seats_max AS FLTP ) AS percentage_fltp WHERE carrier_id = 'LH' AND connection_id = '0400' INTO TABLE @DATA(result). out->write( EXPORTING data = result name = 'RESULT' ).
  3. CTRL + F3 を選択してクラスを有効化し、F9 を選択してコンソールアプリとして実行します。
  4. コンソール出力を分析します。
  5. 独自の算術式を試して、構文をよく理解します。

数値関数

ABAP SQL には、算術式を使用して計算を補完するためのさまざまな組込関数が用意されています。完全な一覧については、ABAP 言語文書を参照してください。

いくつかの重要な数値 SQL 関数は以下のとおりです。

  • 関数 DIV( ) は整数の除算 (余りなし) を実行し、入力として整数値のみが許可されます。
  • 関数 MOD( ) は、このような除算の整数の余りを返します。
  • 関数 DIVISION( ) では、浮動小数点値を除く任意の数値を入力できます。小数結果の精度は、関数の 3 番目のパラメータで指定されます。
  • 関数 ROUND( ) を使用すると、数値を指定された位置に明示的に丸めることができます。

例: ABAP SQL での数値関数の使用

この例は、ABAP SQL における数値関数の使用を示しています。関数 DIV( ) ではパーセント値を整数として計算できますが、関数 DIVISION( ) では結果が小数値として返されます。

なお、48.78787…… が48になるよう、余りのDIV()がカットされる。一方、DIVISION( ) では、商用丸めを使用して指定した小数点以下桁数に丸めるため、48.787878... は 48.78 ではなく 48.79 になります。

試してみる: 数値関数

  1. インタフェース IF_OO_ADT_CLASSRUN を実装する新しいグローバルクラスを登録します。
  2. 以下のコードスニペットをメソッド if_oo_adt_classrun~main( ) の実装部分にコピーします。
    Code Snippet
    1234567891011121314151617181920212223
    SELECT FROM /dmo/flight FIELDS seats_max, seats_occupied, ( CAST( seats_occupied AS FLTP ) * CAST( 100 AS FLTP ) ) / CAST( seats_max AS FLTP ) AS percentage_fltp, div( seats_occupied * 100 , seats_max ) AS percentage_int, division( seats_occupied * 100, seats_max, 2 ) AS percentage_dec WHERE carrier_id = 'LH' AND connection_id = '0400' INTO TABLE @DATA(result). out->write( EXPORTING data = result name = 'RESULT' ).
  3. CTRL + F3 を選択してクラスを有効化し、F9 を選択してコンソールアプリとして実行します。
  4. コンソール出力を分析します。
  5. 数値関数 (部門など) の 1 つにカーソルを置き、F1 を選択して文書を開きます。
  6. 文書で他の数値関数を探し、その機能について理解してみてください。

文字列処理

ABAP では、演算子 && を使用して、文字型の引数を 1 つの長い文字列に結合することができます。この演算子を ABAP SQL で使用して、データベースですでに連結操作を実行することもできます。最初の例では、顧客の敬称、名、および姓がフルネームに結合されます。2 番目の例では、地名、郵便番号、および市区町村名が得意先の住所に結合されます。&& ではどのような種類の区切記号も追加されないため、空白をマニュアルで追加する必要があります。

文字列処理関数

ABAP SQL には、文字列処理用の多くの組込関数も用意されています。完全な一覧については、ABAP 言語文書を参照してください。

ABAP SQL の重要な文字列関数は以下のとおりです。

  • 関数 CONCAT( ) は 2 つの文字列を (空白なしで) 連結します。
  • 関数 CONCAT_WITH_SPACE( ) でも同じ処理が行われますが、指定した数の空白が中央に挿入されます。
  • 関数 UPPER( ) および LOWER( ) は、引数を大文字/小文字に変換します。
  • 関数 INITCAP( ) は LOWER( ) のように機能しますが、各単語の最初の文字を大文字に変換します。
  • 関数 LEFT( ) は、指定された引数から最初の n 文字を抽出します。RIGHT( ) は同じですが、右から開始します。
  • 関数 SUBSTRING( ) は、指定された位置から指定された数の文字を抽出します。

この例では、street、postal_code、city を連結して、顧客の住所を構成します。これは、2 つの異なる方法で行われます。1 回は連結演算子 && を使用し、もう 1 回はネストされた SQL 関数を使用します。

注記

演算子 && は末尾の空白を無視しますリテラル ' ' でのみ空白が保持されます。

この例は、関数 UPPER( )、LOWER( )、および INITCAP( ) の影響を示しています。運送業者名の関数変換 'GmbH' は異なることに注意してください。

この例では、文字列処理関数を使用して、日付フィールドから年、月、および日の情報を抽出します。

注記

日付項目の内部書式は YYYYMMDD であることに注意してください。最初の列のハイフンは、日付項目の出力書式 (ISO 書式) に属します。内部書式では存在しません。日付項目をデータ型 CHAR( 8 ) にキャストすると、内部書式が表示されるようになります。これは、2 番目の列に表示されます。

試してみる: 文字列処理

  1. インタフェース IF_OO_ADT_CLASSRUN を実装する新しいグローバルクラスを登録します。
  2. 以下のコードスニペットをメソッド if_oo_adt_classrun~main( ) の実装部分にコピーします。
    Code Snippet
    1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
    SELECT FROM /dmo/customer FIELDS customer_id, street && ',' && ' ' && postal_code && ' ' && city AS address_expr, concat( street, concat_with_space( ',', concat_with_space( postal_code, upper( city ), 1 ), 1 ) ) AS address_func WHERE country_code = 'ES' INTO TABLE @DATA(result_concat). out->write( EXPORTING data = result_concat name = 'RESULT_CONCAT' ). ********************************************************************** SELECT FROM /dmo/carrier FIELDS carrier_id, name, upper( name ) AS name_upper, lower( name ) AS name_lower, initcap( name ) AS name_initcap WHERE carrier_id = 'SR' INTO TABLE @DATA(result_transform). out->write( EXPORTING data = result_transform name = 'RESULT_TRANSLATE' ). ********************************************************************** SELECT FROM /dmo/flight FIELDS flight_date, cast( flight_date as char( 8 ) ) AS flight_date_raw, left( flight_Date, 4 ) AS year, right( flight_date, 2 ) AS day, substring( flight_date, 5, 2 ) AS month WHERE carrier_id = 'LH' AND connection_id = '0400' INTO TABLE @DATA(result_substring). out->write( EXPORTING data = result_substring name = 'RESULT_SUBSTRING' ).
  3. CTRL + F3 を選択してクラスを有効化し、F9 を選択してコンソールアプリとして実行します。
  4. コンソール出力を分析します。
  5. SELECT 文の FIELDS リストにある式と関数を操作して、構文と関数に習熟します。

データベースでのデータ処理の実行

この演習問題では、空席の計算と、航空会社 ID と航空会社名の連結をデータベースにプッシュダウンします。

テンプレート:

  • /LRN/CL_S4D401_DBS_NESTED_JOIN (グローバルクラス)

ソリューション:

  • /LRN/CL_S4D401_DBS_PUSH_DOWN (グローバルクラス)

タスク 1: テンプレートのコピー (オプション)

テンプレートクラス /LRN/CL_S4D401_DBS_NESTED_JOIN をコピーします。前の演習問題を完了した場合は、このタスクをスキップし、クラス ZCL_##_SOLUTION の編集を続行することができます。

ステップ

  1. クラス /LRN/CL_S4D401_DBS_NESTED_JOIN を各自のパッケージのクラスにコピーします (推奨名: ZCL_##_SOLUTION、## はグループ番号)。

    1. Project Explorer で、クラス /LRN/CL_S4D401_DBS_NESTED_JOIN を右クリックしてコンテキストメニューを開きます。

    2. コンテキストメニューから Duplicate.... を選択します。

    3. Package 項目にパッケージの名称を入力します。Name 項目に、ZCL_##_SOLUTION (## はグループ番号) と入力します。

    4. Next を選択します。

    5. 移送依頼を確認し、Finish を選択します。

  2. コピーを有効化します。

    1. Ctrl + F3 を押してクラスを有効化します。

タスク 2: プッシュダウン計算

ローカルクラス LCL_PASSENGER_FLIGHT で、静的属性 flights_buffer の行データ型をコンポーネント seats_free で拡張します。メソッド GET_FLIGHTS_BY_CARRIER の実装を調整し、SELECT 命令に空席の計算を追加します。次に、CONSTRUCTOR メソッドの実装を調整します。SELECT SINGLE 文に計算を追加し、計算結果を使用してインスタンス属性 seats_free を入力します。

ステップ

  1. ローカルクラス LCL_PASSENGER_FLIGHT で、構造タイプ ST_FLIGHTS_BUFFER の定義にナビゲートします。

    1. たとえば、エディタでローカルタイプタブを開き、BEGIN OF st_flights_buffer を検索することができます。

    2. または、左側のアウトラインビューで ZCL_##_SOLUTIONLCL_PASSENGER_FLIGHT を展開し、ST_FLIGHTS_BUFFER を選択することもできます。

  2. コンポーネント seats_uscuped の後に、インスタンス属性 seats_free と同じタイプの新規コンポーネント seats_free を追加します。

    1. コードを以下のように調整します。

      ABAP
      1234567891011
      TYPES: BEGIN OF st_flights_buffer, carrier_id TYPE /lrn/passflight-carrier_id, connection_id TYPE /lrn/passflight-connection_id, flight_date TYPE /lrn/passflight-flight_date, plane_type_id TYPE /lrn/passflight-plane_type_id, seats_max TYPE /lrn/passflight-seats_max, seats_occupied TYPE /lrn/passflight-seats_occupied, seats_free TYPE i, price TYPE /lrn/passflight-price, currency_code TYPE /lrn/passflight-currency_code, END OF st_flights_buffer.
  3. メソッド GET_FLIGHTS_BY_CARRIER の実装にナビゲートし、SELECT 命令の項目一覧に空席の計算を追加します。

    注意

    計算が構造タイプ ST_FLIGHTS_BUFFER の新規コンポーネントと同じ位置にあることを確認します。または、INTO 句でオプション CORRESPONDING FIELDS OF を使用することもできます。
    1. コードを以下のように調整します。

      ABAP
      12345678
      SELECT FROM /lrn/passflight FIELDS carrier_id, connection_id, flight_date, plane_type_id, seats_max, seats_occupied, seats_max - seats_occupied AS seats_free, price, currency_code WHERE carrier_id = @i_carrier_id INTO TABLE @flights_buffer.
  4. メソッド CONSTRUCTOR の実装にナビゲートし、SELECT SINGLE 命令の項目一覧に空席の計算を追加します。

    1. コードを以下のように調整します。

      ABAP
      12345678910
      SELECT SINGLE FROM /lrn/passflight FIELDS plane_type_id, seats_max, seats_occupied, seats_max - seats_occupied AS seats_free, price, currency_code WHERE carrier_id = @i_carrier_id AND connection_id = @i_connection_id AND flight_date = @i_flight_date INTO CORRESPONDING FIELDS OF @flight_raw.
  5. インスタンス属性 seats_free への値割当まで下にスクロールします。代入演算子の右側にある算術式を fligh_raw-seats_free の内容に置き換えます。

    1. コードを以下のように調整します。

      ABAP
      12345
      planetype = flight_raw-plane_type_id. seats_max = flight_raw-seats_max. seats_occ = flight_raw-seats_occupied. * seats_free = flight_raw-seats_max - flight_raw-seats_occupied. seats_free = flight_raw-seats_free.

タスク 3: プッシュダウン文字列連結

ローカルクラス LCL_CARRIER で、CONSTRUCTOR メソッドの実装を調整します。航空会社 ID と航空会社名の連結を SELECT SINGLE 命令の項目一覧に移動し、結果をインスタンス属性に保存します。

ステップ

  1. ローカルクラス LCL_CARRIER で、CONSTRUCTOR メソッドの実装にナビゲートします。

    1. 前と同じ方法でこのステップを実行します。

  2. name 属性の値割当を見つけます。これを分析してから、コード行の先頭にコメント記号を追加します。

    1. ステートメントまで下にスクロールします name = carrier_id && ` ` && name.

    2. このコード行の任意の場所にカーソルを置き、Ctrl + < を押します。

  3. SELECT SINGLE 命令の項目一覧で、データベーステーブル項目 NAME を適切な文字列処理機能の呼出に置き換えて、1 つのスペースで区切られた ID と航空会社の名称を連結します。

    注記

    または、SELECT SINGLE 命令の項目一覧で carrier_id && ' ' && name を使用することもできます。
    1. コードを以下のように調整します。

      ABAP
      123456
      SELECT SINGLE FROM /lrn/carrier * FIELDS name, currency_code FIELDS concat_with_space( carrier_id, name, 1 ), currency_code WHERE carrier_id = @i_carrier_id INTO ( @me->name, @me->currency_code ).
  4. グローバルクラスをコンソールアプリとして有効化してテストします。

    1. Ctrl + F3 を押します。

    2. F9 を押します。