GitのCodeSpacesを使ってMySQLをざっくり学ぶ③　テーブルの結合

本記事はMySQLについて学習する初学者向けの記事となります。
環境としてCodeSpacesを使用していますが、今回の記事においてはほとんどMySQLについての内容となります。

ちなみにGithubのアカウントが既に登録されている前提で進んでいきますのでご注意ください。

また、GitでCodeScapesを使用する方法・MySQLをインストールする方法については１つ前の記事に記述していますのでそちらをご覧ください。
[GitのCodeSpacesを使ってMySQLをざっくり学ぶ① DBの作成／削除／切替・ユーザーの作成・SQLファイル実行](https://qiita.com/y-wanida/items/ca2fa84b492e3d64747f)

他、テーブルの作成／削除やデータの作成／削除などについての記事もあるので、こちらの記事もぜひご覧になってください。
 [GitのCodeSpacesを使ってMySQLをざっくり学ぶ② テーブルの作成／削除・データの取得／追加／削除／更新](https://qiita.com/y-wanida/items/edaf59d2cad85c0ff6c3)
## 前提
まず、今回の学習環境は下記のようになります。
・Git CodeSpaces
・MySQL（Ver 8.0.40-0）

リポジトリを作成して、CodeSpacesを開いた状態から始めます。

まず最初にMySQLを起動します。
```linux:terminal
$ sudo service mysql start;
```

下記内容のSQLファイルを配置しroot権限で実行します。
```sql:test_file.sql
drop database if exists testdb;
create database testdb;
drop user if exists tester01@localhost;
create user tester01@localhost identified by '12345';
grant all on testdb.* to tester01@localhost;
use testdb;
create table students(id int unsigned, name varchar(32), age int, class varchar(32));
INSERT INTO students (id, name, age, class) VALUES
(1, '太郎', 20, 'A'),
(2, '花子', 22, 'B'),
(3, '次郎', 19, 'C'),
(4, '美咲', 21, 'D'),
(5, '健太', 23, 'C');
create table lessons (id int unsigned, student_id int unsigned, lesson_name varchar(32));
insert into lessons (id, student_id, lesson_name) values
(1, 1, 'Math'),
(2, 1, 'Science'),
(3, 2, 'History'),
(4, 3, 'Math'),
(5, 5, 'Science');
```

```linux:terminal
$ sudo mysql -u root < test_file.sql
```

実行できたら操作対象となるテーブルを選択します。

```sql:terminal
mysql> use testdb;
```

## テーブルの結合
複数のテーブルからデータを取り出し、関連するデータを１つの結果として表示する操作のことです。結合させることで別々のテーブル間で関連性を持つデータを一度に取得できます。

 想像がつきにくいと思うので図で分かりやすい例を図で解説します。

 データの関係性が「１対多」となっている２つのテーブルを用意します。
 この「１対多」というのは、下記の例でいえばstudentsテーブルのレコード１つに対して、
 lessonsテーブルのレコードが複数個紐づくということを表します。

 **studentsテーブル（１）**　**lessonsテーブル（多）**

![段落テキスト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3906686/b0eaec32-aa6e-b07a-9b60-6df5074310c5.png)

レコードはidで一意に特定することができます。そのため、紐付き先のテーブルのidを持つことで
lessonsテーブルのレコードがstudentsテーブルのレコードに関連付けることができます。


![段落テキスト (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3906686/f4819561-32ac-42f9-cba0-00793c9ad476.png)

studentsテーブル側のレコードが増えているように見えますが、実際にstudentsテーブルのレコード数が増えているわけではありません。lessonsテーブルに紐づいているstudentsテーブルのレコードを視覚的に表示しているという認識としてください。
つまり、studentsテーブルとlessonsテーブルの関係性を１つの結合テーブルで表しているということです。


次にテーブル結合を学習するうえで覚えておくと便利なエイリアスについて説明します。
### エイリアス
…テーブル名やカラム名に一時的な別名を付ける機能のことです。
　テーブル結合の有無に関わらず使用することができます。

まず、エイリアスを設定していない状態のテーブルを表示してみましょう。
```sql:terminal
mysql> select * from students;
+------+--------+------+-------+
| id   | name   | age  | class |
+------+--------+------+-------+
|    1 | 太郎   |   20 | A     |
|    2 | 花子   |   22 | B     |
|    3 | 次郎   |   19 | C     |
|    4 | 美咲   |   21 | D     |
|    5 | 健太   |   23 | C     |
+------+--------+------+-------+
5 rows in set (0.00 sec)
```

では、「name」を「namae」に、「class」を「kumi」にエイリアスを設定してテーブルを表示してみましょう。
```sql:terminal
mysql> select name as namae, class as kumi from students;
->
+--------+------+
| namae  | kumi |
+--------+------+
| 太郎   | A    |
| 花子   | B    |
| 次郎   | C    |
| 美咲   | D    |
| 健太   | C    |
+--------+------+
5 rows in set (0.00 sec)
```

このようにわかりやすいカラム名でテーブルを表示することなどができます。

では本題の結合の種類についてご紹介します。
取得したい内容によって無駄なデータが発生しないようにテーブル結合を活用していくことが大事です。
### INNER JOIN （内部結合）
…両方のテーブルに共通するデータのみを取得します。
```sql:terminal
mysql> select students.name, lessons.lesson_name
    -> from students
    -> inner join lessons on students.id = lessons.student_id;

->    
+--------+-------------+
| name   | lesson_name |
+--------+-------------+
| 太郎   | Math        |
| 太郎   | Science     |
| 花子   | History     |
| 次郎   | Math        |
| 健太   | Science     |
+--------+-------------+
5 rows in set (0.00 sec)

```


### LEFT JOIN （左外部結合）
…左側のテーブルのすべてのデータと、右側のテーブルで一致するデータを取得します。一致しない場合はNULLが返されます。

```sql:terminal
mysql> SELECT students.name, lessons.lesson_name
    -> FROM students
    -> RIGHT JOIN lessons ON students.id = lessons.student_id;
+--------+-------------+
| name   | lesson_name |
+--------+-------------+
| 太郎   | Math        |
| 太郎   | Science     |
| 花子   | History     |
| 次郎   | Math        |
| 健太   | Science     |
+--------+-------------+
5 rows in set (0.00 sec)

```

### RIGHT JOIN （右外部結合）
…右側のテーブルのすべてのデータと、左側のテーブルで一致するデータを取得します。一致しない場合はNULLが返されます。

```sql:terminal
mysql> select students.name, lessons.lesson_name
    -> from students
    -> right join lessons on students.id = lessons.student_id;

->
+--------+-------------+
| name   | lesson_name |
+--------+-------------+
| 太郎   | Math        |
| 太郎   | Science     |
| 花子   | History     |
| 次郎   | Math        |
| 健太   | Science     |
+--------+-------------+
5 rows in set (0.00 sec)
```

### CROSS JOIN（クロス結合）
…2つのテーブルの全ての組み合わせを取得します。例えば、片方のテーブルに3件、もう片方に2件のデータがある場合、結果は6件になります。

```
mysql> select students.name, lessons.lesson_name
    -> from students
    -> cross join lessons;
+--------+-------------+
| name   | lesson_name |
+--------+-------------+
| 健太   | Math        |
| 美咲   | Math        |
| 次郎   | Math        |
| 花子   | Math        |
| 太郎   | Math        |
| 健太   | Science     |
| 美咲   | Science     |
| 次郎   | Science     |
| 花子   | Science     |
| 太郎   | Science     |
| 健太   | History     |
| 美咲   | History     |
| 次郎   | History     |
| 花子   | History     |
| 太郎   | History     |
| 健太   | Math        |
| 美咲   | Math        |
| 次郎   | Math        |
| 花子   | Math        |
| 太郎   | Math        |
| 健太   | Science     |
| 美咲   | Science     |
| 次郎   | Science     |
| 花子   | Science     |
| 太郎   | Science     |
+--------+-------------+
25 rows in set (0.00 sec)
```

### SELF JOIN（自己結合）
…同じテーブルを結合する方法です。今回は、学生の名前を比較します。
　また、１テーブルの中で階層構造を持たせている場合は、会社の上司・部下などの関係をデータで表現することもできます。

```sql:terminal
select a.name as student1, b.name as student2
from students a
join students b on a.class = b.class and a.id != b.id;

->
+----------+----------+
| student1 | student2 |
+----------+----------+
| 健太     | 次郎      |
| 次郎     | 健太      |
+----------+----------+
```