MySQL 結合を使用したらエラーが出た

## 目的

- テーブル結合を使用したら「Not unique table/alias」というエラーが出たので解決方法をまとめる

## 実施環境

- ハードウェア環境

| 項目 | 情報 |
| --- | --- |
| OS | macOS Catalina(10.15.5) |
| ハードウェア | MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports) |
| プロセッサ | 2 GHz クアッドコアIntel Core i5 |
| メモリ | 32 GB 3733 MHz LPDDR4 |
| グラフィックス | Intel Iris Plus Graphics 1536 MB |

- ソフトウェア環境

| 項目 | 情報 | 備考 |
| --- | --- | --- |
| MySQLバージョン | 8.0.19 for osx10.13 on x86_64 | Homwbrewを用いてこちらの方法で導入→[Mac HomebrewでMySQLをインストールする](https://qiita.com/miriwo/items/ef6a064bc545fbea29d9) |

## 前提情報

- 架空のマッチングアプリのユーザ情報を格納しているテーブルを用いて説明を行う。
- ユーザ情報としてマッチングしたいユーザID、ユーザ名、マッチングしたい異性の最低年齢、マッチングしたい異性の最高年齢、本人の年齢を格納しているusersテーブルに年齢のレンジを格納しているage_rangesテーブルを結合したい。
-  DB、テーブル、カラム、各データの挿入は下記のSQL、またはコマンドを上から実行して行った。
    1. MySQLのログイン

        ```terminal
        $ mysql -u root -p
        ```
    1. DB．テーブル、カラム、各データの挿入は下記のSQLを実行した。

        ```sql
        create database join_test;
        use join_test;
        create table users(id int, name varchar(255), matching_age_min int, matching_age_max int, age int);
        create table age_ranges( id int, age_range varchar(255));
        insert into users(id, name, matching_age_min, matching_age_max, age) values (1, 'miriwo', 2, 5, 2);
        insert into age_ranges(id, age_range) value(1, '下限なし');
        ```
    1. SQL`show tables;`を実行したときに下記のように表示される。

        ```
        +---------------------+
        | Tables_in_join_test |
        +---------------------+
        | age_ranges          |
        | users               |
        +---------------------+
        2 rows in set (0.00 sec)
        ```
    1. SQL`select * from users;`を実行したときに下記のように表示される。

        ```
        +------+--------+------------------+------------------+------+
        | id   | name   | matching_age_min | matching_age_max | age  |
        +------+--------+------------------+------------------+------+
        |    1 | miriwo |                2 |                5 |    2 |
        +------+--------+------------------+------------------+------+
        1 row in set (0.00 sec)
        ```
    1. SQL`select * from age_ranges;`を実行したときに下記のように表示される。

        ```
        +------+--------------+
        | id   | age_range    |
        +------+--------------+
        |    1 | 下限なし     |
        |    2 | 20代         |
        |    3 | 30代         |
        |    4 | 40代         |
        |    5 | 50代         |
        |    6 | 上限なし     |
        +------+--------------+
        6 rows in set (0.00 sec)
        ```
## テーブルの情報

- usersテーブル

    | カラム名 | データ型 |
    | --- | --- |
    | id | int |
    | name | varchar |
    | matching_age_min | int |
    | matching_age_max | int |
    | age | int |

- age_rangesテーブル

    | カラム名 | データ型 |
    | --- | --- |
    | id | int |
    | age_range | varchar |

## テーブル結合を使って表示したいもの

- usersテーブルとage_rangesテーブルを結合して下記のように表示したい。

    | id | name | matching_age_min | matching_age_max | age |
    | --- | --- | --- | --- | --- |
    | 1 | miriwo | 20代 | 50代 | 20代 |

## 実行したSQLと結果

- テーブル結合の基本に乗っ取り下記のSQLを実行した。

    ```SQL
    select users.id, users.name, age_ranges.age_range, age_ranges.age_range, age_ranges.age_range from users 
    join age_ranges 
    on users.matching_age_min = age_ranges.id 
    join age_ranges 
    on users.matching_age_max = age_ranges.id 
    join age_ranges 
    on users.age = age_ranges.id 
    where users.id = 1;
    ```
- 下記のエラーが出力された。

    ```
    ERROR 1066 (42000): Not unique table/alias: 'age_ranges'
    ```

## 解決策

- 下記のようなSQLを実行すれば問題は解決する、SQL記載後に簡単に説明をする。

    ```sql
    select users.id, users.name, age_ranges_min.age_range, age_ranges_max.age_range, age_ranges_user.age_range from users 
    join age_ranges as age_ranges_min
    on users.matching_age_min = age_ranges_min.id 
    join age_ranges as age_ranges_max
    on users.matching_age_max = age_ranges_max.id 
    join age_ranges as age_ranges_user
    on users.age = age_ranges_user.id 
    where users.id = 1;
    ```
- ポイントは「join句で結合を指定するときにasを使って別名を指定する」である。
- 下記に上記のSQLのjoin句の一部を記載する。

    ```sql
    join age_ranges as age_ranges_min
    on users.matching_age_min = age_ranges_min.id
    ```
- 上記ではjoin句で結合先テーブルを指定するときにasを用いて別名を与えている。直後のon句では結合条件のテーブル名を別名を用いて指定している。
- またselect句でも「join句で指定した別名.カラム名」と指定する事により、select句で出力するカラムの重複を防いでいる。