データサイエンス100本ノック（構造化データ加工編）解説_S021-S026

## はじめに
第四回です。前回はこちら。

https://qiita.com/sato_ryo/items/280961da14b2b0a41bea
### 凡例
- [XXX]：　XXXは省略可能
- (XXX)：　XXXの論理的な名前
- 本来は、`%%sql`を答えの1行目に記載する必要があります。
## 問題
### 21問目：集計関数① 件数カウント
#### S-021: レシート明細データ（receipt）に対し、件数をカウントせよ。

<details><summary>S-021答え</summary>

```sql
SELECT
  COUNT(*)
FROM
  receipt r
;
```
</details>

テーブルのレコード数を算出する際には、`COUNT` を使います。
構文
```sql
SELECT COUNT(*) FROM (テーブル名)
```
'COUNT(列名)'とすると、列名の数を数えます。
列名を指定すると、列名が`NULL`の場合は数えません。
'COUNT(*)'は`NULL`があってもレコードとして存在していれば数えます。
また、 `COUNT(1)`としても同じ結果になります。

https://qiita.com/higakin/items/02f74f35831d8390407d


https://qiita.com/tsubasa_k0814/items/28c643b812287431d175


### 22問目：集計関数② ユニークな件数カウント
#### S-022: レシート明細データ（receipt）の顧客ID（customer_id）に対し、ユニーク件数をカウントせよ。

<details><summary>S-022答え</summary>

```sql
SELECT
  COUNT(DISTINCT customer_id)
FROM
  receipt r
;
```
</details>

重複を排除して件数を算出する場合は `DISTINCT`を列名の前に入れます。


### 23問目：集計関数③ 合計、列ごとの集計
#### S-023: レシート明細データ（receipt）に対し、店舗コード（store_cd）ごとに売上金額（amount）と売上数量（quantity）を合計せよ。

<details><summary>S-023答え</summary>

```sql
SELECT
  store_cd
  , SUM(amount) AS amount
  , SUM(quantity) AS quantity
FROM
  receipt r
GROUP BY
  store_cd
;
```
</details>

合計する際には、`SUM`を使います。
また、テーブルの特定の列の値単位で集計したい際には`GROUP BY`を使います。
構文(合計)
```sql
SELECT SUM( (列名) ) FROM (テーブル名)
```

構文(列名単位の集計)
```sql
SELECT (列名), SUM( (列名) ) FROM (テーブル名) GROUP BY (集計単位の列名)
```
集計関数(上記構文では`SUM`)がなくても`GROUP BY` は使えます。
集計単位の列名は<b>複数</b>指定できます。


### 24問目：集計関数③ 最大最小
#### S-024: レシート明細データ（receipt）に対し、顧客ID（customer_id）ごとに最も新しい売上年月日（sales_ymd）を求め、10件表示せよ。


<details><summary>S-024答え</summary>

```sql
SELECT
  customer_id
  , MAX(sales_ymd) AS sales_ymd
FROM
  receipt r
GROUP BY
  customer_id
;
```
</details>

テーブルのカラムの最大値を算出する際には、`MAX` を使います。
構文
```sql
SELECT MAX((列名)) FROM (テーブル名)
```
23問目と同様、`GROUP BY`と併用可能です。
$一番新しい年月日=最大の年月日$ です。

### 25問目：集計関数④ 最大最小
#### S-025: レシート明細データ（receipt）に対し、顧客ID（customer_id）ごとに最も古い売上年月日（sales_ymd）を求め、10件表示せよ。



<details><summary>S-025答え</summary>

```sql
SELECT
  customer_id
  , MIN(sales_ymd) AS sales_ymd
FROM
  receipt r
GROUP BY
  customer_id
;
```
</details>

テーブルのカラムの最大値を算出する際には、`MIN` を使います。
構文
```sql
SELECT MIN((列名)) FROM (テーブル名)
```
23問目と同様、`GROUP BY`と併用可能です。
$一番新しい年月日=最大の年月日$ です。

### 26問目：集計後の条件比較
### S-026: レシート明細データ（receipt）に対し、顧客ID（customer_id）ごとに最も新しい売上年月日（sales_ymd）と古い売上年月日を求め、両者が異なるデータを10件表示せよ。
<details><summary>S-026答え</summary>

```sql
SELECT
  customer_id
  , MIN(sales_ymd) AS sales_ymd_oldest
  , MAX(sales_ymd) AS sales_ymd_newest
FROM
  receipt r
GROUP BY
  customer_id
HAVING
  MIN(sales_ymd) <> MAX(sales_ymd)
LIMIT 10
;
```
</details>

集計関数を基にした処理は、<b>WHERE句</b>では参照できません。
`GROU BY` で集計した値を用いたり、集計した状態での条件を絞り込みたい場合は `HAVING`を利用します。
また、`SELECT`句でつけた別名は利用できません。

### 27問目：平均値、GROUP BYとORDER BY
### S-027: レシート明細データ（receipt）に対し、店舗コード（store_cd）ごとに売上金額（amount）の平均を計算し、降順でTOP5を表示せよ。

<details><summary>S-027答え</summary>

```sql
SELECT
  customer_id
  , AVG(amount) AS amount_average
FROM
  receipt r
GROUP BY
  store_cd
ORDER BY amount_average DESC
LIMIT 5
;
```
</details>

<b>平均値</b>
平均値は `AVG` 関数を使います。
ソート処理は `SELECT`句の後に実行されるため、SELECT句で指定した別名を利用可能です。



## 参考文献・クレジット

https://github.com/The-Japan-DataScientist-Society/100knocks-preprocess?tab=readme-ov-file

本記事では、以下のライセンスのもと提供されている資料を参考にしています。

### MIT License
© 2020 The Japan DataScientist Society  
[MIT Licenseの詳細](https://opensource.org/licenses/MIT)

### Creative Commons Attribution-NoDerivatives 4.0 International（CC BY-ND 4.0）
[ライセンスの詳細](https://creativecommons.org/licenses/by-nd/4.0/deed.ja)

※ 本記事では、元の内容を改変せずに引用・解説を行っています。

### その他参考文献

https://qiita.com/DeepTama/items/85470a66972432e14224

https://techis.jp/guide/sql/sql_wildcards