【新人教育 資料】第7章 SQLへの道 〜集合関数（SUM、MAX、MIN、AVG、COUNT）編〜

#【新人教育 資料】第7章 SQLへの道 〜集合関数（SUM、MAX、MIN、AVG、COUNT）編〜
## あらすじ
新人がいっぱい入ってくる。新人のレベルもバラバラ。教育資料も古くなっているので、更新しましょう。
どうせなら、公開しちゃえばいいじゃん。という流れになり、新人教育用の資料を順次更新していくことにしました。

※後々、リクエストに応じて更新することが多いのでストックしておくことをおすすめします。

自分は[TEMONA株式会社](http://temona.co.jp/)でCTOをしていますが、頭でっかちに理論ばっかり学習するよりは、イメージがなんとなく掴めるように学習し、実践の中で知識を深めていく方が効率的に学習出来ると考えています。

※他の登壇やインタビュー記事は[Wantedly](https://www.wantedly.com/users/105935)から見てください。


教育スタイルとしては正しい事をきっちりかっちり教えるのではなく、未経験レベルの人がなんとなく掴めるように、資料を構成していきます。

以下のようなシリーズネタで進めます。

|No.|記事|
|:-----------|-----------|
|1|[【新人教育 資料】第1章 SQLへの道 〜DB編〜](http://qiita.com/devopsCoordinator/items/9b70e506150888e190be)|
|2|[【新人教育 資料】第2章 SQLへの道 〜3値論理編〜](http://qiita.com/devopsCoordinator/items/9c10410b50f8fcc2ba79)|
|3|[【新人教育 資料】第3章 SQLへの道 〜基本数学編〜](http://qiita.com/devopsCoordinator/items/08e405a9c58cc203d016)|
|4|[【新人教育 資料】第4章 SQLへの道 〜SQL基本操作編〜](http://qiita.com/devopsCoordinator/items/0f742158caf0fdb533e3)|
|5|[【新人教育 資料】第5章 SQLへの道 〜絞込編〜](http://qiita.com/devopsCoordinator/items/dca5aa9c155292f1c6ea)|
|6|[【新人教育 資料】第6章 SQLへの道 〜ソート編〜](http://qiita.com/devopsCoordinator/items/8cad032aa035dc1cdbc0)|
|7|[【新人教育 資料】第7章 SQLへの道 〜集合関数（SUM、MAX、MIN、AVG、COUNT）編〜](http://qiita.com/devopsCoordinator/items/85918c8508dddf19586f)|
|8|[【新人教育 資料】第8章 SQLへの道 〜グループ編〜](http://qiita.com/devopsCoordinator/items/f74228615982932c914b)|
|9|[【新人教育 資料】第9章 SQLへの道 〜結合編〜](http://qiita.com/devopsCoordinator/items/3ba154429973a4ddc9e0)|

では、今回もはじめていきましょう！

# SQL 集合関数（SUM、MAX、MIN、AVG、COUNT）
集合関数とは、SQLに備わっている演算機能です。Excelある機能と類似しているので、馴染みのある方も多いかと思います。
集計関数,集約関数と言ったりすることもあります。
集合関数には主に次の5つがあります。

|関数名|意味|
|:-----------|-----------|
|COUNT|総数を求める|
|SUM|総和を求める|
|MAX|最大値を求める|
|MIN|最小値を求める|
|AVG|平均を求める|

これを使いこなせれば,「SQLって便利じゃん!!」となること請け合いです。

# 基本編
[【新人教育 資料】第5章 SQLへの道 〜絞込編〜](http://qiita.com/devopsCoordinator/items/dca5aa9c155292f1c6ea)
で使ったデータを元に話を進めます。
導入されていない方は下記のレポジトリをForkして、Readmeを参考に環境構築をしてください。
https://github.com/TEMONA/mysql_study

※全てにおいて自己責任でお願いします。

全ての基本構造は下記の形です。

```sql
SELECT 関数名(カラム名) FROM テーブル名
```

個別に見ていきましょう。
## COUNT
countは総数です。「このテーブルのレコードは幾つなんだろう」「大分県生まれの方は何人いるのだろう」という際に利用します。

「このテーブルのレコードは幾つなんだろう」

```sql
select count(*) from users;
```
![1__Default__mysql_.jpg](https://qiita-image-store.s3.amazonaws.com/0/103225/eaaadd2d-a3cc-f7a1-2144-942d40248fd0.jpeg)
アスタリスク【*】は全てをあらわします。
users というテーブルには1000行あることがわかります。

「大分県生まれの方は何人いるのだろう」

```sql
select count(*) from users where birthplace = '大分県';
```

![2.jpg](https://qiita-image-store.s3.amazonaws.com/0/103225/2d51526b-ee57-d3dd-dced-dd7d04fc7051.jpeg)
もちろんwhere枠も使えます。大分県生まれは15人ですね。
## SUM
sumは総和です。「合計金額はいくらだろう」といった際に利用します。
「合計金額はいくらだろう」

```sql
select sum(price) from lineitems;
```
![3.jpg](https://qiita-image-store.s3.amazonaws.com/0/103225/02391df3-f9fb-e590-cad7-e61761feb420.jpeg)
【price】と言うカラムの総和なので

```
sum(price)
```
です。

当然ですが、計算できる値でなければダメです。
![4.jpg](https://qiita-image-store.s3.amazonaws.com/0/103225/f2524cb2-7b2c-1883-d9d9-a4d59fdc5103.jpeg)

## MAX
maxは最大値です。
当然ですが、これも最大がある値でなければダメです。
![5.jpg](https://qiita-image-store.s3.amazonaws.com/0/103225/31a11d4b-8424-419b-f87c-9330a1e61f7f.jpeg)

```sql
select max(age) from users where birthplace = '大分県';
```

## MIN
minは最小値です。
当然ですが、これも最小がある値でなければ...
![6.jpg](https://qiita-image-store.s3.amazonaws.com/0/103225/2317c59e-a45b-0213-e583-16f04d807819.jpeg)

```sql
select count(*),max(age),min(age) from users where birthplace = '大分県' and gender_id = 0;
```
このように、集合関数同士同時に利用できます。

## AVG
avgは平均値です。
当然ですが、これも平均を取れる値で...
![7.jpg](https://qiita-image-store.s3.amazonaws.com/0/103225/54fa3d3f-51df-b508-2eb9-5cdc2f8097cc.jpeg)

```sql
SELECT count(*) AS 総数,
       max(age) AS 最高齢,
       min(age) AS 最年少,
       avg(age) AS 平均年齢
FROM users
WHERE birthplace = '大分県';
```
どんどん長くなるため、わかりやすく改行しています。大文字の部分がありますが、もちろん小文字でも問題ありません。
【as】は名前をつけます。この場合はわかりやすくするためです。

これで基本編は終了です。

## 「ちょっと寄り道〜サブクエリ編〜」
[【新人教育 資料】第5章 SQLへの道 〜絞込編〜](http://qiita.com/devopsCoordinator/items/dca5aa9c155292f1c6ea)
でちらりとでてきたサブクエリーを使ってみるとこんなこともできます。
![8.jpg](https://qiita-image-store.s3.amazonaws.com/0/103225/f0f58bbf-f81c-33f9-f24b-ad309e5f5a93.jpeg)

```sql
SELECT sum(price) AS 大分県生まれ最高年齢購買合計金額
FROM lineitems
WHERE order_id IN
    (SELECT id
     FROM orders
     WHERE user_id IN
         (SELECT id
          FROM users
          WHERE birthplace = '大分県'
            AND age IN
              (SELECT max(age)
               FROM users
               WHERE birthplace = '大分県')));
```

長いのでやる気を失うかもしれませんが、今まででてきた知識で読むことができます。
分解して考えてみましょう。
まず末端から見ていきます。
①

```sql
SELECT max(age)
FROM users
WHERE birthplace = '大分県'
```
上記に出てきたSQLです。
大分県生まれの方の最高年齢を出しています。

徐々に範囲を広げます。
②

```sql
SELECT id
FROM users
WHERE birthplace = '大分県'
  AND age IN
    (SELECT max(age)
     FROM users
     WHERE birthplace = '大分県')
```
大分県生まれの方の最高年齢の方のusersのidを出しています。
上記の①がSQLの中に入っていることがわかります。

①の値がわかっているのでわかるかと思います。
このSQLのwhereにも

```sql
WHERE birthplace = '大分県'
```
があるのは、これが無いと
①の年齢の人全員が対象になってしまうためです。
こうするとわかりやすいでしょうか。
![9.jpg](https://qiita-image-store.s3.amazonaws.com/0/103225/ec8bcc55-66f6-a35a-7902-fe65aa9eaa5f.jpeg)

後はわかりますね。
③

```sql
SELECT id
FROM orders
WHERE user_id IN
    (SELECT id
     FROM users
     WHERE birthplace = '大分県'
       AND age IN
         (SELECT max(age)
          FROM users
          WHERE birthplace = '大分県'))
```
これで大分県生まれ最高年齢の方のordersのidを出しています。
これを繰り返せばいくらでも長く書くこともできます。

# 演習
・全顧客の最大の誕生日と最小の誕生日を取得
・1980年代生まれの方の注文合計数を取得
・20代の方の購買合計金額を取得

# 参考文献
mysql5.6 リファレンスマニュアル:https://dev.mysql.com/doc/refman/5.6/ja/

# あとがき
今回の集合関数編は以上です。
実際にプログラムに組み込む際は、言語などで開発しているアプリケーション側で計算をさせるべきか、データべース側で計算させるべきか
みたいな判断も必要になってきます。

次回は「【新人教育 資料】第8章 SQLへの道 〜グループ編〜」をお送りする予定です