Railsを学習してる者たちよ、SQLを学べ！

## SQLを学ぼうと思ったきっかけ

Railsで自作アプリを作っているときにN+1問題に直面した。

includesやleft_joinとかを学習してるときに、SQLの動きをちゃんとわかってないとやばくね？って思った。

Railsはあくまでフレームワークだ。本来SQL直書きするところを簡単にしてくれている。

なのでSQLをある程度わかっていたら、もし違うプログラミング言語で組むことになったとき、フレームワークであれば関連づけて覚えやすいし、直書きなら普通に書ける。

実際にSQLを勉強してみたら意外とすんなり頭に入ってくれた。何も怖がることはなかったので勉強しておくとあとあと絶対いいはず！

この記事では、結合とグループ化について書いていく。

## テーブルの結合

```
Usersテーブル
+----+--------+
| id | name   |
+----+--------+
|  1 | user１  |
|  2 | user2  |
+----+------- +

Articlesテーブル
+----+--------+-------+---------+
| id | title  | body  | user_id |
+----+--------+-------+---------+
|  1 | title1 | body１ |       1 |
|  2 | title２ | body２ |       1 |
|  3 | title３ | body３ |       2 |
|  4 | title４ | body４ |         |
+----+--------+-------+---------+
```

上記の２つのテーブルがあるとします。

### INNER JOIN（内部結合）

articleのuser_idとusersのidを紐づけている。

```SQL
select articles.*, users.name 
from articles inner join users 
on articles.user_id = users.id;
```
出力結果

```
+----+--------+-------+---------+-------+
| id | title  | body  | user_id | name  |
+----+--------+-------+---------+-------+
|  1 | title1 | body1 |       1 | user1 |
|  2 | title2 | body2 |       1 | user1 |
|  3 | title3 | body3 |       2 | user2 |
+----+--------+-------+---------+-------+
```

**articles.user_idとusers.idが一致しているデータだけ**を出力している。

なので、Articlesテーブルのid = 4のデータはuser_idを持っていないので出力されていない。

### LEFT JOIN（外部結合）

`LEFT OUTER JOIN`は`LEFT JOIN`と同じ意味。

SQL

```SQL
select articles.*, users.name 
from articles left join users 
on articles.user_id = users.id;
```
出力結果

```
+----+--------+-------+---------+-------+
| id | title  | body  | user_id | name  |
+----+--------+-------+---------+-------+
|  1 | title1 | body1 |       1 | user1 |
|  2 | title2 | body2 |       1 | user1 |
|  3 | title3 | body3 |       2 | user2 |
|  4 | title4 | body4 |         |       |
+----+--------+-------+---------+-------+
```

articlesテーブルとuserテーブルを並べるようなイメージ。

左のテーブル(articlesテーブル)を基準に結合している。

articlesテーブルはwhereの条件にあてはまる全件が出力され、それに紐づくusersのデータが出力されている。

ちなみにwhere句の条件なしの表現は `where 1 = 1` 

### RIGHT JOIN（外部結合）

LEFT JOINの逆なので省略



## グループ化

```
Teamsテーブル
+----+-------+-------+
| id |  team | point |
+----+-------+-------+
|  1 | teamA |   3   |
|  2 | teamB |   2   |
|  3 | teamA |   5   |
|  4 | teamB |   4   |
|  5 | teamC |  10   |
|  6 | teamC |  20   |
+----+-------+-------+
```

上記のテーブルがあるとします。

### Group by

SQL

```sql
select team, sum(point) from teams group by team;
```

出力結果

```
+----+-------+-------+
| id |  team | point |
+----+-------+-------+
|  1 | teamA |   8   |
|  2 | teamB |   6   |
|  3 | teamC |  30   |
+----+-------+-------+
```

teamカラムを基準にpointを合計している。
今回扱ったのはsum()合計やけど他にも色々あるで。

例：

- COUNT(team)　

```SQL
select team, sum(point) from teams group by team;
```

```
レコードのカウント数
+----+-------+-------+
| id |  team | COUNT |
+----+-------+-------+
|  1 | teamA |   2   |
|  2 | teamB |   2   |
|  3 | teamC |   2   |
+----+-------+-------+
```

- avg(point)では平均pointが出力される。

#### where句の位置

SQL

```SQL
select team, sum(point) from teams where team != "teamB" group by team;
```

出力結果

```
+----+-------+-------+
| id |  team | point |
+----+-------+-------+
|  1 | teamA |   8   |
|  2 | teamC |  30   |
+----+-------+-------+
```

### Having句

group byした結果をさらに条件をつける。

SQL

```SQL
select team, sum(point) from teams where team != "teamB" 
group by team having sum(point) > 10;
```

出力結果

```SQL
+----+-------+-------+
| id |  team | point |
+----+-------+-------+
|  1 | teamC |  30   |
+----+-------+-------+
```

何をしているかというと、

**team != "teamB"の条件でグループ化**

**グループ化した結果をさらにsum(point) > 10の条件で検索**

Havingはグループ化した後のwhere句みたいなかんじ。

余計わかりにくいかな。

## おわり

他にもいろいろあるけど、とりあえず今回は結合とグループ化までで。

これがわかっただけでもRailsで走っているSQLだいたい読めると思う。

記事書いてるときたまたま見つけたサイト。

https://www.1keydata.com/jp/sql/sql-intersect.php

じゃ。