SELECT (For All Entries、 JOIN)
17.3 SELECT (For All Entries、 JOIN)
3. SELECT (For All Entries、 JOIN)
ここでは、データベースのアクセス方法として以下を説明します。
- 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)
REPORT ZCUSLIST1_INTERNAL_ALLENTRIES. DATA wa_data TYPE ZTEST_TBL_002. DATA: t_data TYPE STANDARD TABLE OF ZTEST_TBL_002, "取得用 t_index TYPE STANDARD TABLE OF ZTEST_TBL_001. "検索用 START-OF-SELECTION. *(1) 生徒情報マスタ(ZTEST_TBL_001)から以下のデータを内部テーブルへ読み込みます。 SELECT * FROM ZTEST_TBL_001 INTO TABLE t_index WHERE grade = 1 AND class = 'A' AND num <= 2. *(2) (1)で用意した内部テーブルを検索用内部テーブルとして、 * 生徒別テスト得点情報テーブル(ZTEST_TBL_002)の読み込みを行います。 * 以下の生徒別テスト得点情報テーブルデータから、 * 検索用内部テーブルと検索キー項目(grade,class,num)が一致するデータを読み込みます。 SELECT * FROM ZTEST_TBL_002 INTO TABLE t_data FOR ALL ENTRIES IN t_index WHERE grade = t_index-grade AND class = t_index-class AND num = t_index-num. *ヘッダの帳票出力 WRITE: 001(4) '学年', 010(2) '組',020(8) '出席番号', 030(10) 'テスト名', 050(4) '国語', 055(4) '英語', 060(4) '数学', /001(65) '************************************************'. LOOP AT t_data INTO wa_data. *(3) (2)で読み込んだ内部テーブルを帳票出力します。 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, 055(3) wa_data-english, 060(3) wa_data-math. NEW-LINE. ENDLOOP.
データが読み込まれるまでの流れ
データベーステーブル:ZTEST_TBL_002(生徒別テスト得点情報テーブル)から、項目:GRADE(学年)、CLASS(組)、NUM(出席番号)の値が、検索用内部テーブル:T_INDEXの項目:GRADE(学年)、CLASS(組)、NUM(出席番号)の値と一致(赤枠部分)するデータを取得し、取得用内部テーブル:T_DATAに格納します。(緑枠部分)