【SQL入門】プログラム初心者が最初に学んだSQLを復習するための練習帳《その2》

プログラミング超初心者がSQL入門編を学び、次へ進もうとすると忘れるため備忘録目的で記事を書きました。その第2弾です。

具体的な取り組み方法[^1]。

取り組むときの注意[^2]。

[^1]: 回答用のファイル(mdファイル)を別途用意して練習帳(この記事)のコードをコピーする。回答用の中にある《答え》の部分を《回答欄》に置き換え、すべてのコードを削除。回答用のファイルをVSコードで開き、コードを書く。やり方は[Qiitaの【Markdown記法 チートシート】を活用してMarkdownをマスターする！《答え編》](https://qiita.com/asuka-80/items/296885245cc27ad46f87)と同じ要領です。

[^2]:mdファイルに書いているのでMarkdownと異なり、コードを間違えても気づきにくいです。


# 練習帳で使うテーブル

:::note
![SQL-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3439948/99de64a4-6b5b-60e9-e2de-541b018ac5a4.png)

:::

### 《問題①》&thinsp;`asuka_purchases`テーブルから重複するデータを除いた`name`カラムのデータを取得する
#### 《答え①》
 ```sql:ex.sql
SELECT DISTINCT name
FROM asuka_purchases;
 ```  
|name|
|:--:|
|煙草|
|お菓子|
|芋焼酎|
|焼酎|
|みかん|

### 《問題②》&thinsp;`asuka_purchases`テーブルから`name`と`price`カラム、そして`price`カラムの価格データに消費税(10％)をかけた値を取得する
#### 《答え②》
 ```sql:ex.sql
SELECT name, price*1.1
FROM asuka_purchases;
 ```
|name|price|price*1.1|
|:--:|:--:|:--:|
|煙草|600|660|
|お菓子|150|165|
|芋焼酎|300|330|
|お菓子|200|220|
|焼酎|1000|1100|
|みかん|NULL|NULL|

:::note  
数値と`NULL`を四則演算すると`NULL`になる  
:::

### 《問題③》&thinsp;`asuka_purchases`テーブルからお菓子の合計金額を取得する
#### 《答え③》
 ```sql:ex.sql
SELECT SUM(price)
FROM asuka_purchases
WHERE name = "お菓子";
 ```  

|SUM(price)|
|:--:|
|350|

### 《問題④》&thinsp;`asuka_purchases`テーブル内のお菓子の平均金額を取得する
#### 《答え④》

 ```sql:ex.sql
SELECT AVG(price)
FROM asuka_purchases
WHERE name = "お菓子";
 ```  

|AVG(price)|
|:--:|
|175|　　


### 《問題⑤》`asuka_purchases`テーブルのレコードの数と`price`カラムのデータ数、そしてお菓子のデータ数をそれぞれ取得する
#### 《答え⑤》
 ```sql:ex.sql
SELECT COUNT(*)
FROM asuka_purchases;

/* 『price』カラムのデータ数 */
SELECT COUNT(price)
FROM asuka_purchases;

/* 『price』カラムのデータ数 */
SELECT COUNT(*)
FROM asuka_purchases;
WHERE name = "お菓子";
 ```  

|COUNT(*)|
|:--:|
|6|　

|COUNT(price)|
|:--:|
|5|　　

|COUNT(*)|
|:--:|
|2|　

:::note  
COUNT関数でカラム名を指定した場合、nullになっているデータの数は計算に含まれない  
:::


### 《問題⑥》`price`カラムのデータの内、一番高い価格は何円？また、お菓子の中で一番安い金額は？
#### 《答え⑥》
 ```sql:ex.sql
SELECT MAX(price)
FROM asuka_purchases;

/* 『お菓子』の中で一番安い価格は？ */
SELECT MIN(price)
FROM asuka_purchases
WHERE name = "お菓子";
 ```  
|MAX(price)|
|:--:|
|1000|　
  

|MIN(お菓子)|
|:--:|
|150|　

### 《問題⑦》日付毎にグループ化して、各グループごとの合計金額を集計する
#### 《答え⑦》
 ```sql:ex.sql
SELECT SUM(price), date
FROM asuka_purchases
GROUP BY date;
 ```  

|SUM(price)|date|
|:--:|:--:|
|1050|2023-05-01|
|200|2023-05-16|
|1000|2023-05-17|
||2023-05-18|

:::note  
**GROUP BYについて**  
① GROUP BYを用いる場合SELECTで使えるのは、集計関数とGROUP BYに指定しているカラム名のみ!!  
② 今回『2023-05-18』のグループでNULL(みかん)のみだったが、この日付に購入した項目が他にもあり、例えば焼酎1000円もあるとすると、みかんのNULLの値は無視されて合計金額は「1000」で出力される。  
:::
### 《問題⑧》日付毎にグループ化して、各グループごとの購入数を取得
#### 《答え⑧》
 ```sql:ex.sql
SELECT COUNT(name), date
FROM asuka_purchases
GROUP BY date;
 ```  

|COUNT(name)|date|
|:--:|:--:|
|3|2023-05-01|
|1|2023-05-16|
|1|2023-05-17|
|1|2023-05-18|

### 《問題⑨》日付と購入品ごとにグループ化した合計金額を取得
#### 《答え⑨》
 ```sql:ex.sql
SELECT SUM(price), date, name 
FROM asuka_purchases
GROUP BY date, name;
 ```  
:::note  
今回、同日中に複数の同じ項目を購入していないため、元データ(`asuka_purchases`テーブル)と同じ結果がでる。  
:::

### 《問題⑩》`name`が`お菓子`であるレコードを検索し、日付毎にグループ化し、各グループの`price`合計と`date`カラムを取得する。
#### 《答え⑩》
 ```sql:ex.sql
SELECT SUM(price), date
FROM asuka_purchases
WHERE name = "お菓子"
GROUP BY date;
 ```  
|SUM(price)|date|
|:--:|:--:|
|150|2023-05-01|
|200|2023-05-16|


### 《問題⑪》&thinsp;⑨でWHEREを使って`category`が『飲み物』であるデータの場合の日付と合計価格、購入品(name)を取得する
#### 《答え⑪》
 ```sql:ex.sql
SELECT SUM(price), date, name
FROM asuka_purchases
WHERE category = "飲み物"
GROUP BY date, name;
 ```  

|SUM(price)|date|name|
|:--:|:--:|:--:|
|300|2023-05-01|芋焼酎|
|1000|2023-05-17|焼酎|

### 《問題⑫》日付と購入品毎の合計金額のうち、1000円以上の合計データのみを取得する
#### 《答え⑫》
 ```sql:ex.sql
SELECT SUM(price), date, name
FROM asuka_purchases
GROUP BY date, name
HAVING SUM(price) >= 1000;
 ```  

|SUM(price)|date|name|
|:--:|:--:|:--:|
|1000|2023-05-17|焼酎|

**【実行される順番】**
```plantuml
@startuml
file f1 as "WHERE(検索)"
file f2 as "GROUP BY(グループ化)"
file f3 as "SUMなどの集計関数"
file f4 as "HAVIN(グループ化されたデータが検索対象)"
f1 --> f2
f2 --> f3
f3 --> f4
@enduml
```

### 《問題⑬》`category`でグループ化し、各カテゴリー毎の金額合計と`category`カラムのデータを取得
#### 《答え⑬》
 ```sql:ex.sql
SELECT SUM(price),category 
FROM asuka_purchases
GROUP BY category;
 ```  

|SUM(price)|category|
|:--:|:--:|
|600|嗜好品|
|350|食べ物|
|1300|飲み物|


### 《問題⑭》WHEREで`category`が『飲み物』であるレコードを検索し、商品(name)毎にグループ化し、`price`カラムの合計と商品(name)を取得する
#### 《答え⑭》
 ```sql:ex.sql
SELECT SUM(price), name
FROM asuka_purchases
WHERE category = "飲み物"
GROUP BY name;
 ```  

|SUM(price)|name|
|:--:|:--:|
|300|芋焼酎|
|1000|焼酎|