SQL基本まとめ(集計関数、グループ化)

# はじめに
SQLの基本(集計関数、グループ化)を自分なりにまとめました。
以下で紹介する`DISTINCT`や四則演算、関数は主に`SELECT`で使います。

# DISTINCT 重複データ削除
構文:`DISTINCT(カラム名)`
これで自動的にカラムの重複データを削除してくれる。
```sql
SELECT DISTINCT(name) 
FROM closet;
```

# 四則演算
例えば、消費税を含んだ値にしたいとき。
`カラム名 * 1.1`のようにする。指定したカラムの各全データに1.1をかけた値が取れる。
```sql
SELECT name, price * 1.1
FROM closet;
```
四則演算は`ORDER BY`で使うこともある。
例えば、買った服をフリマアプリで売った時の差額の大きい順を考える。
```sql
SELECT name, buyPrice - sellPrice
FROM closet
ORDER BY buyPrice - sellPrice DESC;
```

# SUM関数　合計を求める
構文：`SUM(カラム名)`
以下は、クローゼット内の服の合計額を求めるとき。
```sql
SELECT SUM(price)
FROM closet;
```
実行結果
| SUM(price) |
|:-:|
|12000|

SUM関数はWHEREと一緒に使える。
以下は、ドレスシャツの合計額を求めるとき。
```sql
SELECT SUM(price)
FROM closet;
WHERE name = "ドレスシャツ";
```

# AVG関数 (avarage: 平均値)
平均を求めたい時。
`AVG(カラム名)`
```sql
SELECT AVG(price)
FROM closet;
```
実行結果
| AVG(price) |
|:-:|
|4000|
```sql
SELECT AVG(price)
FROM closet;
WHERE name = "ドレスシャツ";
```

# COUNT関数 いくつか数える
カラムのデータ数を数えたい時。
`COUNT(カラム名)`
NULLのデータは数えない。
```sql
COUNT(price)
```
nullも含めて数えたい時は*(全てのカラム)を指定する。
これはレコードの数を数える。
```sql
SELECT COUNT(*)
FROM closet;
```
WHEREで条件を絞れる。
```sql
SELECT COUNT(*) --レコードの数
FROM closet
WHERE name = "ドレスシャツ";　--レコードの数から条件に一致するものだけに絞る
```

# MAX・MIN 関数 最大・最小
最大・最小を求めるとき。
並び替えてもよいが、一発で求められる。
`MAX(カラム名)`
`MIN(カラム名)`
最も値段の高いアイテムのデータ。
```sql
SELECT MAX(price)
FROM closet;
```
WHEREと一緒に。ドレスシャツで一番高いもの。
```sql
SELECT MAX(price)
FROM closet;
WHERE name = "ドレスシャツ";
```
以上、集計関数について。

***

ここからグループ化について。

# GROUP BY グループ化
例えば、日付(date)ごとに金額の合計を取りたいとき。
`GROUP BY カラム名`を使う。
指定したカラム名で、完全に同じデータが、自動的にグループになる。
`FROM`の後ろに`GROUP BY カラム名`を書く。
```sql
SELECT SUM(price), date --2.集計する
FROM closet
GROUP BY date; --1.グループ化して
```
出力例
| SUM(price) | date |
|:-:|:-:|
| 3000 | 2022-09-01 |
| 4000 | 2022-09-03 |
| 5000 | 2022-09-07 |

:::note
`GROUP BY`でグループ化されているときに、集計関数(SUM,AVG,COUNTなど)を使うと、グループごとに集計される。
:::

:::note warn
`GROUP BY`を使うとき、`SELECT`で使えるのは、
`GROUP BY`で指定したカラム名と、集計関数(SUM,AVGなど)のみ。
:::

:::note
なので反対に、`SELECT`で使いたいカラムは、`GROUP BY`しておく。
:::

```sql:誤り
SELECT price, date --priceは使えない。SUM(price)なら可.
FROM closet
GROUP BY date; 
```
グループでまとめるので、取るデータもまとめたものだけ。
日付"ごと"とあったら、`GROUP BY`を使う。

# GROUP BY (複数)
複数のカラムでもグループ化ができる。例えば、日付と名前など。
構文：`GROUP BY カラム１, カラム2, ...`
コンマで繋げる。
```sql
SELECT SUM(price), date, name 
FROM closet
GROUP BY date, name;
```
データの組み合わせの数だけグループができる。

各グループごとに集計ができる。
`SELECE SUM(price), date, name`や
`SELECE COUNT(*), date, name`など。


# GROUP BY (WHERE)
より細かい条件でグループ化をしたいとき、`WHERE`を使う。
`WHERE`を先に
`GROUP BY`を後に書く。
実行順は、以下の表の通り。

| 上から順に実行 |SQL |
|:-:|:-:|
| 検索  | WHERE  |
| グループ化  | GROUP BY  |
|  関数 | COUNT, SUM, AVG, MAX, MIN  |

例えば、日付とカテゴリーごとに、ドレスシャツに使ったお金の合計を取得するときは、
1. WHEREで名前が"ドレスシャツ"のレコードを検索する。
2. 日付とカテゴリーでグループ化する。
3. 集計関数で集計する。

以上の順になる。コードを書くと、以下のようになる。
```sql
SELECT SUM(price), date, category
FROM closet
WHERE name = "ドレスシャツ" --1. ドレスシャツのレコードを検索
GROUP BY date, category; --2. 日付とカテゴリーでグループ分け
```

# HAVING
グループ化して集計した後、さらにしぼりこむ時に使う。
例えば、グループ化して、合計金額を集計した後、さらに合計金額が4000円を超えたものに絞り込むとき、
`HAVING`を使って`HAVING　SUM(price) >= 4000`と書く。

`GROUP BY カラム名`　が先で、
`HAVING 条件`が後にくるようにする。
実行順は以下の通り。
| 上から実行 | SQL |
|:-:|:-:|
| 検索  |  WHERE |
| グループ化  | GROUP BY  |
| 関数  | COUNT, SUM, AVG, MAX, MIN  |
| 条件絞り込み  | HAVING  |

`WHERE`と`HAVING`の違いは、
`WHERE`はグループ化される前のテーブル全体が対象で、
`HAVING`は`GROUP BY`でグループ化されたデータが対象。

なので、`HAVING`は、必ずグループ化されたデータのカラムを使う。

:::note
グループ化した後のデータを絞り込みたいなら、`HAVING`を使う。
集計関数で絞り込む時は、`HAVING`。`WHERE`ではない。
:::
```sql
SELECT SUM(price), date
FROM closet
WHERE name = "ドレスシャツ" 
GROUP BY date,
HAVING SUM(price) > 4000; --必ずグループ化されたデータのカラムを使う。 
```
以上、グループ化について。