SQL学習入門 ｜ INNER JOINとOUTER JOINの違いを実例で解説

※JOIN構文の学習内容を整理した記事です。
内容に誤りなどありましたら、ご指摘いただけますと幸いです。

# 初めに
本記事は、SQLにおけるJOIN構文の基礎を整理し、INNER JOINとOUTER JOINの違いを実例とともに解説する入門記事です。

# JOINとは？
JOIN句は2つ以上のテーブルを結合するためのSQL構文です。
JOIN句では対応するカラムを指定し、それらの値が一致する行を結びつけます。

対応するカラムとは`主キー`と`外部キー`を使用します。
`主キー`：主キー(primary key)とはテーブルAにおける一意の識別子（例：id）
`外部キー`：外部キー(Foreign Key)とはテーブルBに存在し、テーブルAの主キーを参照するカラム（例：user_id）

JOINには大きく分けて`INNER JOIN`と`OUTER JOIN`が存在します。
一見似ていますが、取得できるデータの範囲に大きな違いがあります。本記事ではこの違いを具体例を交えて詳しく見ていきましょう。

# INNER JOINとは
まずINNER JOINの動きを見ていきましょう。
前回までで作成したusersテーブルとitemsテーブルを使用していきます。

構文
```
SELECT * FROM テーブルA INNER JOIN テーブルB ON 条件
```
※INNERの句は省略可能ですが、今回はわかりやすくするため、省略せずに記載します。
この構文を使用することで、テーブルAとテーブルBで条件が合致するレコードを結合することができます。
実際に動かしていきましょう。
```sql
SELECT * FROM users INNER JOIN items ON users.id=items.user_id;
```

### 結果
実際に動かしてみると、結果にusersとitemsのデータが結合しているのがわかります。
しかし、同名のカラムはクエリ結果上で自動的にリネームされる（例：name → name_1）ため、可読性が落ちます。
そのため、少しわかりやすく調整しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2155918/a6cdb7ae-6029-4546-b599-d00ffdf02ab8.png)

## カラムの調整
以下のようにSQL文を調整することで、カラムに別名をつけてわかりやすくすることができます。
```sql
SELECT users.name AS 'ユーザー名', users.id, items.user_id, items.name AS '商品名', items.price FROM users INNER JOIN items ON users.id=items.user_id;
```
※`カラム名 AS 別名`とすることで表示される名称を変更できます。
このように`INNER JOIN`を使用することで、左右のテーブルを結合して表示することができます。
今回の場合は`users`テーブルの`id`と`items`テーブルの`user_id`を結合条件として使用しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2155918/9973fa09-92fc-44e1-9a26-48822a504dee.png)

業務で使用する際も、複数のテーブルにまたがってデータが格納されていることが多く、それらのデータを一度に取得したい場合、`JOIN`句を使用します。

# LEFT OUTER JOIN
次に`LEFT OUTER JOIN`を見ていきましょう
```
SELECT * FROM テーブルA LEFT OUTER JOIN テーブルB ON 条件
```
※OUTERの句は省略可能です。

上記構文を使用することで`INNER JOIN`同様テーブル同士を結合することができます。
動作の違いを見ていきましょう。

```sql
SELECT users.name AS 'ユーザー名', users.id, items.user_id, items.name AS '商品名', items.price AS '価格'  FROM users LEFT OUTER JOIN items ON users.id=items.user_id;
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2155918/69747186-e97f-4f17-86f6-37dcecfbf54d.png)

`INNER JOIN`では両方のテーブルに一致するデータがないと表示されませんが、
`OUTER JOIN`では結合条件に一致するデータがなくても、指定したテーブルのデータはすべて出力されます。
`OUTER JOIN`では`RIGHT`と`LEFT`で主となるテーブルを指定できます。
今回の`LEFT`の場合は`テーブルA LEFT OUTER JOIN テーブルB`のうち`テーブルA`に存在するカラムはすべて出力されます。
その際に、`テーブルB`にデータが存在しない場合はテーブルBのカラムがすべて`NULL`となって結合します。

# RIGHT OUTER JOIN
`RIGHT OUTER JOIN`は`LEFT OUTER JOIN`とは異なり、右側のテーブルにある全データを出力します。

今回は`RIGHT OUTER JOIN`を確認するために新たにテーブルとデータを作成します。

#### テーブル作成
```sql
CREATE TABLE reservation (
    id int AUTO_INCREMENT primary key,
    reservation_user_id int,
    reservation_day DATE,
    created_by varchar(50),
    updated_by varchar(50),
    created_at timestamp DEFAULT CURRENT_TIMESTAMP,
    updated_at timestamp DEFAULT CURRENT_TIMESTAMP,
    delete_flg boolean
)
```
#### ダミーデータ挿入
基本的に自動連番で大丈夫です。
終了値を70に設定しておきましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2155918/a23f2a45-c089-413b-b328-aa46d45ded53.png)
※エラーが発生する場合は「id」のフォーマットを「NULL」に変更しましょう。

#### usersのダミーデータ削除
reservationテーブルのみにデータがある状態にしたいので
61以降のusersテーブルのデータがある場合はすべて削除しましょう。
reservationテーブルは70レコード作成したため、60～70までのデータがusersテーブルで存在しない状態になります。

```sql
delete from users WHERE id > 60;
```
削除が完了しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2155918/4bdf0031-759b-40ca-b6c2-783c73908941.png)


## 結合処理
それでは実際に動作を見ていきましょう。
以下が構文です。
```
SELECT * FROM テーブルA RIGHT OUTER JOIN テーブルB ON 条件
```
実際のSQL
```sql
SELECT users.name AS 'ユーザー名', users.id, reservation.reservation_user_id, reservation.reservation_day AS '予約日' FROM users 
RIGHT OUTER JOIN reservation 
ON reservation.reservation_user_id = users.id;
```
このように右側に設定している`reservation`テーブルにあるレコードがすべて出力されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2155918/6c445aed-9685-4820-80ed-fe0db7efdc84.png)



簡単にまとめると
- **INNER JOIN**：両方のテーブルに一致するデータが存在する場合のみ表示
- **OUTER JOIN**：
  - **LEFT OUTER JOIN**：左側のテーブルの全データを基準に結合
  - **RIGHT OUTER JOIN**：右側のテーブルの全データを基準に結合

# まとめ
今回は以下の構文に関して詳しく解説していきました。
- `INNER JOIN`
- `OUTER JOIN`

これらの語句は業務でもたびたび使用することがあるので、しっかり覚えておきましょう。

次回は集計関数(COUNT/SUM/GROUP BY/HAVING)について学習していきます。
引き続き、SQLの基礎力を高める学習記事を投稿していきます！

[前：SQL学習入門 | WHERE/ORDER BY/GROUP BY/HAVING　基本構文を学習してみた](https://qiita.com/suica1010/items/17ea0f22e1b6750984f1)

参考文献
[【22日間で学ぶ】SQL文、分析関数、テーブル設計、SQLチューニングまでMySQLで覚えるSQL実践講座](https://www.udemy.com/course/3sqlmysql/)