【SQL書籍勉強会】SQLの集計

## 背景

前回の[『SQLとは？』](https://qiita.com/vit_udon_husqy/items/8d7e749fd92cde6dafec)に続き、今回は<b>集計方法</b>についてまとめていこうと思います。

＊本記事は私が学習コミュニティで書籍勉強会を企画したときの発表資料です。
企画概要概要は以下の通り。
・[スッキリわかるSQL入門](https://www.amazon.co.jp/%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%8F%E3%81%8B%E3%82%8BSQL%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E3%83%89%E3%83%AA%E3%83%AB222%E5%95%8F%E4%BB%98%E3%81%8D-%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E4%B8%AD%E5%B1%B1%E6%B8%85%E5%96%AC/dp/4295005096)を読み、自分なりの解釈でまとめてみる
・メンバー四人で各１章ずつを担当して読み、Qiita等でまとめて発表
・全12章あるので3日程で1周。（今回は第2回目！！）
・著作権/剽窃等は必ず配慮します。もし該当箇所あれば削除/修正しますのでお気軽にご指摘ください。


## 集計関数

SQLには集計関数として、以下が用意されている
今回も初学者として、Excelと比較してみましょう。

||SQL集計関数|Excel関数|
|---|---|---|
|合計|SUM|SUM|
|平均|AVG|AVERAGE|
|MAX|MAX|MAX|
|MIN|MIN|MIN|

AVGが省略表記ということ以外は全部同じですね！
でも書き方は違います。

Excelでは `=関数(対象範囲)` という書き方が基本だと思います。
`=SUM(A1:A5)`みたいな感じですね。

それに対し、SQLはこんな感じ

### SUM/AVG/MAX/MIN

```SQL
SELECT
  SUM (計算対象) AS 合計(カラム名)
  AVG (計算対象) AS 平均(カラム名)
  MAX (計算対象) AS 最大値(カラム名)
  MIN (計算対象) AS 最小値(カラム名)
FROM テーブル名
```

`出力してね (SELECT)

何というカラム名として　(AS)
計算対象をどのように (SUM / AVG / MAX / MIN)
どこのテーブルから (FROM)`

という感じで出力できる。
一つ一つの意味がわかれば簡単ですね！

実例) 
![スクリーンショット 2021-07-16 10.46.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1161057/a7e506ad-7655-35a7-601e-ca5acd0a863c.png)


### count

COUNTは値の集計というよりも「データの<b>レコード数</b>の集計」という方が伝わりやすいかも。
こんな感じで使います。

```SQL
SELECT
COUNT( 列 or * ) AS レコード数（カラム名)
FROM テーブル名
WHERE カラム名 = '対象項目'
```

`出力してね(SELECT)
何というカラム名として(AS)
データの数を(COUNT)
( * の場合は ) ただし、NULLも含めてね 
どこのテーブルから (FROM)
カラム名の中の対象項目だけに絞り込んでね (WHERE)`

実例) *レイアウトわかりづらいけど、右下に小さく２と出ています！
![スクリーンショット 2021-07-16 11.49.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1161057/bb2a9118-3fa5-3f8a-6ca1-68cf477e704a.png)

#### NULLについて
これはExcelにおける 空白の扱い方と似ている。
基本的には計算結果に影響を与えない、つまり<b>集計対象から除外される</b>。


## データのグループ化

今度はデータのグループ化を解説。
今回もExcelと比較してみましょう。
わかりづらいものは身近なわかりやすいものに変換。（もちろんその後に正しく理解）

||SQL|Excel|
|---|---|---|
|グループ集計|GROUP BY|PIVOTテーブル|

賛否あるかもしれないけど、個人的にはこれが一番近いと思います。
PIVOTテーブルは範囲を指定して、列ごとに集計する使い方が一般的と思います。
（もちろん他にも色々できるが、、）

ではSQLのGROUP BYは？？

```SQL
SELECT 基準カラム名,
集計関数 (カラム名)
FROM テーブル名
(WHERE カラム名 = '対象項目')
GROUP BY 基準カラム名
```

`基準カラム名を出力するよ
集計関数で集計してね
何というテーブルから
(絞り込みもしたり)
費目ごとにね`
という感じ？

実例) 費目ごとに集計
![スクリーンショット 2021-07-16 17.24.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1161057/f04ab676-a333-21eb-e9f0-9f4935bcbf10.png)


複数のカラムを基準に集計するときはこう。

![スクリーンショット 2021-07-16 17.19.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1161057/d51c51b5-f984-841e-a18f-1984f9ecb941.png)

少し例のデータが少なすぎてわからなくなってしまっているけど、
基準列をカンマで区切ることで、日付をグループ化かつ費目のグループ化された表が表示される。
もっとデータがたくさんあったら以下のような感じで出せるはず。

|日付|費目|出金額|
|---|---|---|
|2018-01-13|食費|350|
|2018-01-13|水道光熱費|400|
|2018-01-13|居住費　|600|


### ポイント
SELECTとGROUP BYで同じことを書かなきゃいけないのは、
・ SELECTではカラムとして表示するものを指定
・ GROUP BYではグループ化するものを指定
ということだと思われます。
（本当のこと知ってる方、コメントでこっそり教えて下さい。)


### 集計後の絞り込み

WHERE句の中で集計関数を用いて絞り込むことはできません。

```SQL
WHERE SUM(カラム名) > 0  
```
という感じはできない。
これは、WHERE句の処理段階ではまだ集計関数が処理されていないからです。

なので、集計後に絞り込みをかけたい場合は <b>HAVING句</b>を使います。

```SQL
SELECT 基準カラム名,
集計関数 (カラム名)
FROM テーブル名
(WHERE カラム名 = '対象項目')
GROUP BY 基準カラム名
HAVING 集計関数 比較演算子等
```

例えば以下を

|日付|費目|出金額|
|---|---|---|
|2018-01-13|食費|350|
|2018-01-13|水道光熱費|400|
|2018-01-13|居住費　|600|

HAVING SUM (出金額) > 380 とすることで、、、

|日付|費目|出金額|
|---|---|---|
|2018-01-13|水道光熱費|400|
|2018-01-13|居住費　|600|

というように絞り込めます。



## まとめ

- 初見できついなと思ったらExcelと比較して考えてみましょう。

- <b>集計関数</b>は四則演算をしてくれたり、最大/最小/平均…などいろんなことを計算してくれる。
機械学習/統計など興味がある方は、分散とか標準偏差なども出せるのでぜひ調べてみてください。

- <b>GROUP BY</b>は集計したものをグループ毎にまとめてくれる。

- <b>HAVING</b>とWHEREは両方絞り込みの機能。よく似ているけど、使う場面が集計前後で異なる。


## 参考
・[スッキリわかるSQL入門](https://www.amazon.co.jp/%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%8F%E3%81%8B%E3%82%8BSQL%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E3%83%89%E3%83%AA%E3%83%AB222%E5%95%8F%E4%BB%98%E3%81%8D-%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E4%B8%AD%E5%B1%B1%E6%B8%85%E5%96%AC/dp/4295005096)
・[逆引きSQL構文集](https://www.sql-reference.com/summary/summary.html)
・[ITSakura Blog for business and development](https://itsakura.com/sql-groupby-having)

## 過去記事
・[【SQL書籍勉強会】SQLとは？](https://qiita.com/vit_udon_husqy/items/8d7e749fd92cde6dafec)

## メンバー記事
・[SQL入門のまとめ②](https://qiita.com/akihiro-cmd/items/4c931ea91763e074e704)
・[[SQL]SQL入門](https://qiita.com/yasu-graz/items/568523e5cb9d4f739fcb)
・[データベースの真価は「テーブルの結合」にあり！](https://qiita.com/Issei_401/items/9c0716f661d8432d3aa7)