INNER JOINとOUTER JOINの違い
言葉で書くとそのままですね。
- INNER JOIN(内部結合)
- OUTER JOIN(外部結合)
それでは取得されるデータはどう変わるのでしょうか。
サンプルデータ
キー項目(CARRID)を結合条件として、2つのテーブルの結合をした場合の違いを確認します。
①INNER JOIN
左右のテーブルの結合条件が合致するデータのみ取得するのがINNER JOINです。
絵で表すと、円が重なった部分のみが取得対象になります。
サンプルコード
SELECT
scarr~carrid,
scarr~carrname,
spfli~connid
FROM scarr
INNER JOIN spfli
ON spfli~carrid = scarr~carrid
INTO TABLE @it_main.
②LEFT OUTER JOIN
左テーブルの全レコードと結合条件に合致する右テーブルを取得するのがLEFT OUTER JOINです。結合条件に合致しない右テーブルの項目の値は取得されません。
サンプルコード
SELECT
scarr~carrid,
scarr~carrname,
spfli~connid
FROM scarr
LEFT OUTER JOIN spfli
ON spfli~carrid = scarr~carrid
INTO TABLE @it_main.
③RIGHT OUTER JOIN
右テーブルの全レコードと結合条件に合致する左テーブルを取得するのがRIGHT OUTER JOINです。結合条件に合致しない左テーブルの項目の値は取得されません。
項目IDとAirlineは左テーブルの値を取得しているので、結合条件に合致しない左テーブルのデータは取得されていません。
サンプルコード
SELECT
scarr~carrid,
scarr~carrname,
spfli~connid
FROM scarr
RIGHT OUTER JOIN spfli
ON spfli~carrid = scarr~carrid
INTO TABLE @it_main.
LEFT OUTER JOINとRIGHT OUTER JOIN
結論から先に書くと、RIGHT OUTER JOINを使うことはまずないです。
なぜなら、LEFT OUTER JOINと動きが同じだからです。テーブルの左右を入れ替えれば全く同じ結果が得られます。
実際のプロジェクトでもRIGHT OUTER JOINが使われているところは見たことがありません。
テーブル結合は最低限INNER JOINとLEFT OUTER JOINの2つを覚えておけば十分です。
ABAP 7.40以降で使える表現
外部結合時の条件(WHERE句)指定
まずは新旧ABAPでの書き方を比較してみましょう。
※実行環境はABAP7.52
ABAP740未満(不可)
SELECT
scarr~carrid
scarr~carrname
spfli~connid
INTO TABLE it_main
FROM spfli
LEFT OUTER JOIN scarr
ON scarr~carrid = spfli~carrid
WHERE scarr~carrid IN s_carrid.
ABAP740以降(可能)
SELECT
scarr~carrid,
scarr~carrname,
spfli~connid
FROM spfli
LEFT OUTER JOIN scarr
ON scarr~carrid = spfli~carrid
WHERE scarr~carrid IN @s_carrid
INTO TABLE @it_main.
実際に両者を書いてみると、左側の従来の書き方では有効化時にエラーが発生します。
(ABAP7.40以降の環境でも、従来の書き方をすれば有効化エラーになります)
理由は、従来のABAPではWHERE句に外部結合先のテーブル項目を指定できないから、です。
従来のABAPでWHERE句に指定できるのは、
- 内部結合なら左右どちらのテーブル項目も指定可
- 外部結合なら元テーブル(LEFT OUTER JOINなら左テーブル)の項目のみ指定可
という制限がありました。
そのため従来のABAPではやり方を工夫して、WHERE句に指定するのが単一項目(= で指定できる)なら結合条件(JOIN句)の中で指定する、レンジテーブルではその手法も使えないので、まず大元のテーブルを取得し、FOR ALL ENTRIES INでもう一方のテーブルを取得するなどの対応をしてました。
それがABAP7.40以降は、新しい表現で書くことによって、WHERE句に外部結合先のテーブル項目を指定できるようになりました。
新しいABAPでは以下のルールがあるので、最初は慣れないと思いますが注意してください。
- 複数項目を抽出する際、最終項目以外はカンマで区切る
- 外部変数(内部テーブルや変数、選択画面項目にはエスケープ文字(@)を付与
もう一つ、INTO TABLEの位置が新旧で異なりますが、これもABAP7.40以降の新しい表現で、INTO TABLEを文末に持ってくることができるようになりました。ただし、従来通りの位置に書くこともできるので、好みの問題だと思います。
個人的には、内部テーブルを上の方に書くと、デバッグの際に探しにいくのが面倒なので、文末に書けるのは地味に嬉しいポイントだと思っています。
外部結合テーブルに対する外部結合
見出しだけだとわかりづらいですね。今までは2つのテーブルを結合する場合のコードを見てきましたが、ここで紹介するのは3つ以上のテーブルを結合する場合の話です。
図で表すとこんな感じで、左テーブルと中テーブルを外部結合、中テーブルと右テーブルも外部結合をします。
ABAP740未満(不可)
SELECT
scarr~carrid
scarr~carrname
spfli~connid
sflight~fldate
INTO TABLE it_main
FROM scarr
LEFT OUTER JOIN spfli
ON spfli~carrid = scarr~carrid
LEFT OUTER JOIN sflight
ON sflight~carrid = spfli~carrid
AND sflight~connid = spfli~connid.
ABAP740以降(可能)
SELECT
scarr~carrid,
scarr~carrname,
spfli~connid,
sflight~fldate
FROM scarr
LEFT OUTER JOIN spfli
ON spfli~carrid = scarr~carrid
LEFT OUTER JOIN sflight
ON sflight~carrid = spfli~carrid
AND sflight~connid = spfli~connid
INTO TABLE @it_main.
上記サンプルコードのように、従来のABAPでは外部結合テーブルに対する外部結合は認められていませんので、元テーブルのない外部結合をしたい場合は新しいABAPで書くようにしてください。
※右テーブル(SFLIGHT)の結合元が左テーブル(SCARR)であれば従来のABAPでも可能です
まとめ
- INNER JOINは結合するテーブルの両方に存在するデータが取得される
- OUTER JOINは元テーブル全件と結合条件に合致するデータが取得される
- 新しいABAP(7.40)では外部結合で便利な文法が追加された
INNER JOIN、OUTER JOINはABAP開発でよく使われる文法の一つですので参考にしてください。