【ABAP】SQL - INNER JOIN / OUTER JOIN

<!-- wp:paragraph -->ABAPでSELECT処理でよく使われるINNER JOINとOUTER JOINについて、具体的に何が違うのか見ていきます。新しいABAPで追加された手法も紹介します。

## INNER JOINとOUTER JOINの違い

言葉で書くとそのままですね。

- INNER JOIN（内部結合）
- OUTER JOIN（外部結合）

それでは取得されるデータはどう変わるのでしょうか。

### サンプルデータ

キー項目（CARRID）を結合条件として、2つのテーブルの結合をした場合の違いを確認します。

- ![](https://sapmemo.com/wp-content/uploads/2020/08/SCARR.png)左テーブル（SCARR）
- ![](https://sapmemo.com/wp-content/uploads/2020/08/drawit-diagram-1.png)右テーブル（SPFLI）

### ①INNER JOIN

左右のテーブルの結合条件が合致するデータのみ取得するのがINNER JOINです。

絵で表すと、円が重なった部分のみが取得対象になります。

- ![](https://sapmemo.com/wp-content/uploads/2020/08/inner-join.png)
- ![](https://sapmemo.com/wp-content/uploads/tuik//image14-wpp1597151264292.png)

サンプルコード

 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です。結合条件に合致しない右テーブルの項目の値は取得されません。

- ![](https://sapmemo.com/wp-content/uploads/2020/08/image-e1597155101479.png)
- ![](https://sapmemo.com/wp-content/uploads/2020/08/image14-wpp1597154827598.png)

サンプルコード

 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は左テーブルの値を取得しているので、結合条件に合致しない左テーブルのデータは取得されていません。

- ![](https://sapmemo.com/wp-content/uploads/2020/08/drawit-diagram-2.png)
- ![](https://sapmemo.com/wp-content/uploads/tuik//image14-wpp1597242090867.png)

サンプルコード

 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.





![](https://sapmemo.com/wp-content/uploads/2020/08/image-1.png)

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.





![](https://sapmemo.com/wp-content/uploads/2020/08/image-2.png)



実際に両者を書いてみると、左側の従来の書き方では有効化時にエラーが発生します。

（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つ以上のテーブルを結合する場合の話です。

図で表すとこんな感じで、左テーブルと中テーブルを外部結合、中テーブルと右テーブルも外部結合をします。

![](https://sapmemo.com/wp-content/uploads/2020/08/drawit-diagram-5-wpp1597470672497.png)それでは、以下の3つのテーブルで見ていきます。

- ![](https://sapmemo.com/wp-content/uploads/2020/08/SCARR.png)左テーブル（SCARR）
- ![](https://sapmemo.com/wp-content/uploads/2020/08/SPFLI-1.png)中テーブル（SPFLI）
- ![](https://sapmemo.com/wp-content/uploads/2020/08/drawit-diagram-7.png)右テーブル（SFLIGHT）

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.





![](https://sapmemo.com/wp-content/uploads/2020/08/image-3.png)

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.





![](https://sapmemo.com/wp-content/uploads/2020/08/image-4.png)



上記サンプルコードのように、従来のABAPでは外部結合テーブルに対する外部結合は認められていませんので、元テーブルのない外部結合をしたい場合は新しいABAPで書くようにしてください。

※右テーブル（SFLIGHT）の結合元が左テーブル（SCARR）であれば従来のABAPでも可能です

## まとめ

- INNER JOINは結合するテーブルの両方に存在するデータが取得される
- OUTER JOINは元テーブル全件と結合条件に合致するデータが取得される
- 新しいABAP（7.40）では外部結合で便利な文法が追加された

INNER JOIN、OUTER JOINはABAP開発でよく使われる文法の一つですので参考にしてください。