SELECT (For All Entries、 JOIN)
17.3 SELECT (For All Entries、 JOIN)
3. SELECT (For All Entries、 JOIN)
ここでは、データベースのアクセス方法として以下を説明します。
SELECT(JOIN)
JOINは「結合」とも呼ばれ、一度のSELECT命令で、複数テーブルからレコードを抽出することが可能です。また結合には内部結合と外部結合の2種類があります。
内部結合
内部結合は、結合しているすべてのテーブルに存在するデータを抽出します。
抽出する際に、結合しているすべてのテーブルにデータが存在しない場合は、
抽出せずにスキップします。
外部結合
外部結合は、基準となるテーブルにデータが存在する場合に抽出します。
内部結合と違い、結合しているすべてのテーブルにデータが存在しない場合も抽出します。
つまり、該当レコードが、スキップされずにすべて取得されます。
SELECT(JOIN)FROM句
結合なしのSELECT命令と同様に、FROM句には抽出先のデータベーステーブルを指定します。
また、結合する場合に限り、選択したテーブルに任意の別名をつけることができ、データベーステーブル名を逐一、書く必要がなくなります。
この別名は、同SELECT命令外では、機能しないので注意しましょう。
抽出元のデータベーステーブルは<DBtab1>で、<別名1>と記します、という意味です。
SELECT(JOIN)INNER JOIN(内部結合)/OUTER JOIN(外部結合)句
ここでは、FROM句で指定したテーブルと、結合させたいデータベーステーブルを指定することができます。
FROM句と同様に、抽出先のデータベーステーブルに、任意の別名をつけることができます。
内部結合するデータベーステーブルは<DBtab2>で、<別名2>と記します、という意味です。
外部結合するデータベーステーブルは<DBtab2>で、<別名2>と記します、という意味です。
SELECT(JOIN)ON句
ここでは、結合条件を指定します。
この結合条件を満たしたレコードからのみ抽出することができます。
これにより、任意の項目を抽出したとしても、結合先のデータベーステーブルから抽出するデータとの整合性を保つことができます。
条件の指定方法は、WHERE句とほぼ同様ですが、それぞれの項目名が、どのデータベースの項目なのかを記述する必要があります。
データベーステーブル<DBtab1>の<項目名1>と、データベーステーブル<DBtab2>の<項目名2>が等しいレコードを結合しなさい、という意味です。
SELECT(JOIN)WHERE句
WHERE句は抽出条件を指定します。
結合なしのSELECT文と異なる点は、複数テーブルから同時に抽出するため、
条件を記述する際に、それぞれの項目名が、どのデータベースの項目なのかを記述する必要があります。
SELECT INNER JOINの構文例
この構文例の意味について、コードの記載順に説明していきます。
ここでは、データベーステーブルから抽出する項目を指定しています。
抽出する項目は、
Aの項目:CARRID(航空会社コード)
Aの項目:CONNID(フライト接続番号)
Aの項目:FLDATE(フライト日付)
Bの項目:CITYFROM(到着都市)
Bの項目:CITYTO(出発都市)
となります。
(※AとBについては次で説明しています。)
FROM句には、抽出したいデータベーステーブル名を記述します。
データベーステーブル:SFLIGHT(フライト)から抽出し、別名をAと記します。
INNER JOIN句には、 結合させたいデータベーステーブル名を記述します。
データベーステーブル:SPFLI(フライトスケジュール)を内部結合し、別名をBと記します。
ON句には、結合条件が書かれています。
Aの項目:CARRID(航空会社コード)が、Bの項目:CARRID(航空会社コード)と等しい、かつ、Aの項目:CONNID(フライト接続番号)が、Bの項目:CONNID(フライト接続番号)に等しいデータを結合します。
内部結合ですので、AとB両方のデータベーステーブルにデータが存在するレコードのみ結合されます。
INTO TABLE句には、取得したデータを格納する内部テーブルを指定します。
取得したデータは内部テーブル:TAB_FLIGHTに格納します。
WHERE句では、抽出条件を指定しています。
Aの項目:FLDATE(フライト日付)が、2021年12月31日より前のデータが抽出対象になります。
構文例の内部結合のイメージ
SELECT LEFT OUTER JOINの構文例
先ほどの内部結合の構文例との違いは、青字部分の記載が、
LEFT OUTER JOIN(外部結合)か、INNER JOIN(内部結合)か、のみです。
この構文例の意味については、コードの違う以下の部分についてのみ説明します。
LEFT OUTER JOIN句には、 結合させたいデータベーステーブル名を記述します。
データベーステーブル:SPFLI(フライトスケジュール)を外部結合し、別名をBと記します。
構文例の外部結合のイメージ
SELECT(For All Entries)
For All Entries命令では、指定した内部テーブルに含まれるレコードの項目の組み合わせを抽出対象として、一括検索することができます。
ループで、内部テーブルの値を1件ずつ抽出条件に指定しなくても、FOR ALL ENTRIESを
使えば、一括で抽出することができます。
注意事項
ただし、指定した検索用内部テーブルが0件の場合は、全件選択となってしまうため、
FOR ALL ENTRIES を使用する前には、必ずIF命令などを利用して、検索用内部テーブルの件数を確認しましょう。
データが読み込まれるまでの流れ
この例では、検索用内部テーブルを検索条件として、DBテーブルからデータを読み込み、取得用内部テーブルに格納しています。
すなわち、DBテーブルから、
項目:Aの値が001、かつ、項目:Bの値がAのレコード、
および
項目:Aの値が003、かつ、項目:Bの値がCのレコード、
を読み込み、取得用内部テーブルに格納しています。
サンプルコード SELECT(For All Entries)
1 | REPORT ZCUSLIST1_INTERNAL_ALLENTRIES. |
2 | DATA wa_data TYPE ZTEST_TBL_002. |
3 | DATA: t_data TYPE STANDARD TABLE OF ZTEST_TBL_002, "取得用 |
4 | t_index TYPE STANDARD TABLE OF ZTEST_TBL_001. "検索用 |
8 | *(1) 生徒情報マスタ(ZTEST_TBL_001)から以下のデータを内部テーブルへ読み込みます。 |
9 | SELECT * FROM ZTEST_TBL_001 INTO TABLE t_index |
10 | WHERE grade = 1 AND class = 'A' AND num <= 2. |
12 | *(2) (1)で用意した内部テーブルを検索用内部テーブルとして、 |
13 | * 生徒別テスト得点情報テーブル(ZTEST_TBL_002)の読み込みを行います。 |
14 | * 以下の生徒別テスト得点情報テーブルデータから、 |
15 | * 検索用内部テーブルと検索キー項目(grade,class,num)が一致するデータを読み込みます。 |
19 | FOR ALL ENTRIES IN t_index |
20 | WHERE grade = t_index-grade |
21 | AND class = t_index-class |
24 | WRITE: 001(4) '学年', 010(2) '組',020(8) '出席番号', 030(10) 'テスト名', |
25 | 050(4) '国語', 055(4) '英語', 060(4) '数学', |
26 | /001(65) '************************************************'. |
28 | LOOP AT t_data INTO wa_data. |
29 | *(3) (2)で読み込んだ内部テーブルを帳票出力します。 |
30 | WRITE: /001(1) wa_data-grade, 010(2) wa_data-class, 020(2) wa_data-num, 030(10) wa_data-testname, 050(3) wa_data-japanese, |
31 | 055(3) wa_data-english, 060(3) wa_data-math. |
データが読み込まれるまでの流れ
データベーステーブル:ZTEST_TBL_002(生徒別テスト得点情報テーブル)から、項目:GRADE(学年)、CLASS(組)、NUM(出席番号)の値が、検索用内部テーブル:T_INDEXの項目:GRADE(学年)、CLASS(組)、NUM(出席番号)の値と一致(赤枠部分)するデータを取得し、取得用内部テーブル:T_DATAに格納します。(緑枠部分)
出力結果
NEXT>> 第18章 ABAP SQL③