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

## はじめに
SQLの知識の整理のために、SQLの基本が綺麗に纏まっているデータサイエンス100本ノック（構造化データ加工編）　の解説を記事を作成しました。
### 凡例
- [XXX]：　XXXは省略可能
- (XXX)：　XXXの論理的な名前
## 問題
### 1問目：全ての項目を表示・出力件数指定 
#### S-001レシート明細データ（receipt）から全項目の先頭10件を表示し、どのようなデータを保有しているか目視で確認せよ。
<details><summary>S-001答え</summary>

```sql
%%sql
SELECT
  r.*
FROM
  receipt r
LIMIT 10;
```
</details>

<b>構文</b>
```SQL
SELECT
  [(テーブル名).](列名)
FROM
  (テーブル名)
```
<b>全列取得</b>
SELECT句に「*」を記載すると全ての列を取得することができます。

<b>出力件数指定</b>
省略可能です。DBによって異なります。
| DBMS | 構文 |
|:-:|:-:|
| MySQL・SQLite |` SELECT [列名] FROM  [テーブル]`<br>` LIMIT [件数]`|
| SQLServer |` SELECT TOP (件数/割合) [PERCENT]`<br>`(列名) FROM (テーブル)`|
| Oracle 12 |` SELECT (列名) FROM (テーブル) `<br>`FETCH FIRST (件数) ROWS ONLY`|
| Oracle (古い) |` SELECT (列名) FROM (テーブル) `<br>`WHERE ROWNUM <= (件数)`|

<b>テーブル名指定</b>
JOIN等がなく、テーブルが1つの場合は SELECT句のテーブル名は不要ですが、明示的に記載しておくとミスを減らせるケースがあります。

### 2問目：列名を指定して抽出
#### S-002: レシート明細データ（receipt）から売上年月日（sales_ymd）、顧客ID（customer_id）、商品コード（product_cd）、売上金額（amount）の順に列を指定し、10件表示せよ。
<details><summary>S-002答え</summary>

```sql
%%sql
SELECT
  r.receipt
  ,r.sales_ymd
  ,r.customer_id
  ,r.product_cd
  ,r.amount
FROM
  receipt r
LIMIT 10;
```
</details>

<b>列名指定</b>
「*」は簡易的にデータを見たい場合、データ量が少ないケースに使うのは良いですが、
保守性、性能の観点から利用するカラムに絞って明示的にカラムを指定すべきでしょう。
| 観点 | 概要 |
|:-:|:-:|
|処理性能低下| メモリの消費、データ転送スピードの低下(Webアプリ)|
| 保守性 | 想定しない列の追加、削除による影響を受ける  |
<b>カンマの位置</b>
私は後ろカンマだと、SQLのカラムの追加の際にカンマを消し忘れするため、前カンマを利用しています。可読性を優先して、流儀やコーディング規約等によって適切に記載しましょう。

### 3問目：カラムに別名(エイリアス)をつける
#### S-003: レシート明細データ（receipt）から売上年月日（sales_ymd）、顧客ID（customer_id）、商品コード（product_cd）、売上金額（amount）の順に列を指定し、10件表示せよ。ただし、sales_ymdをsales_dateに項目名を変更しながら抽出すること。
<details><summary>S-003答え</summary>

```sql
%%sql
SELECT
  r.receipt
  ,r.sales_ymd AS sales_date
  ,r.customer_id
  ,r.product_cd
  ,r.amount
FROM
  receipt r
LIMIT 10;
```

</details>

<b>構文</b>
```sql
SELECT (列名) AS (別名) FROM (テーブル名)
```
別名に日本語をつける場合には「'」等で囲う必要があります。
ASは多くのDBMSで省略できますが、SQLServerでは、列名ASは省略できません。

### 4問目：特定の条件のデータを抽出
#### S-004: レシート明細データ（receipt）から売上日（sales_ymd）、顧客ID（customer_id）、商品コード（product_cd）、売上金額（amount）の順に列を指定し、以下の条件を満たすデータを抽出せよ。
- 顧客ID（customer_id）が"CS018205000001"
 
<details><summary>S-004答え</summary>

```sql
%%sql
SELECT
  r.receipt
  ,r.sales_ymd
  ,r.customer_id
  ,r.product_cd
  ,r.amount
FROM
  receipt r
WHERE
  customer_id = "CS018205000001"
```

</details>

#### 条件指定
WHERE (条件)　で特定の条件のデータのみに絞り込みができます。
構文
```sql
SELECT (列名) FROM (テーブル名) WHERE (条件)
```
一般的なプログラミング言語と違い `A = B` は代入ではなく、<b>AとBが等しい</b>という式です。
この問題では、`customer_id = "CS018205000001"`　とすればよいです。
#### 文字列リテラル
文字列の定数のようなものを　文字列リテラル　と読んだりします。
DBによって異なりますが、「'」、「"」を囲むと文字列リテラルになります。



### 5問目： 複数の条件を満たすデータの抽出
#### S-005: レシート明細データ（receipt）から売上日（sales_ymd）、顧客ID（customer_id）、商品コード（product_cd）、売上金額（amount）の順に列を指定し、以下の全ての条件を満たすデータを抽出せよ。

- 顧客ID（customer_id）が"CS018205000001"
- 売上金額（amount）が1,000以上
 
<details><summary>S-005答え</summary>

```sql
%%sql
SELECT
  r.receipt
  ,r.sales_ymd
  ,r.customer_id
  ,r.product_cd
  ,r.amount
FROM
  receipt r
WHERE
  customer_id = "CS018205000001"
  AND amount >= 1000
```

</details>

#### 複数条件
条件①と条件②の両方を満たす場合は ① AND ② と記載します。
構文
```sql
SELECT (列名) FROM (テーブル名) WHERE (条件①) AND (条件②) ...
```

## 参考文献・クレジット
、「データサイエンティスト協会スキル定義委員」の「データサイエンス100本ノック（構造化データ加工編）」を利用しております。

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://analytics.leverages.jp/entry/2022/02/16/080000

https://wa3.i-3-i.info/word19037.html

https://oss-db.jp/dojo/dojo_02