【SQL】SQL初心者用練習問題

# SQLの練習問題
## 対象読者
1. SQLをついこないだ勉強し始め、軽い問題を解いてみたい人

※想定実行環境はSQL Serverです

## 問題一覧
+ 問1. (x,y,z)のうち最大の数字を表示してください

    samplesテーブル
    |id|x|y|z|
    |----|---:|---:|---:|
    |A| 10| 20| 30|
    |B| 15| 10| 5|
    |C| 200| 300| 100|
    |D| 5| 5| 3|

    ↓

    期待結果

    |id|greatest|
    |--|-:|
    |A| 30|
    |B| 15|
    |C| 300|
    |D| 5|

    + [オンライン実行環境(sqlfiddle)](https://sqlfiddle.com/sql-server/online-compiler?id=fd332ba0-1289-4298-aa0f-d4e5d1fe034d)
    <details><summary>解答</summary>

    ```sql
    SELECT
        id
        ,CASE
            WHEN
                CASE WHEN x < y THEN y ELSE x END < z
            THEN
                z
            ELSE
                CASE WHEN x < y THEN y ELSE x END
            END AS GREATEST_BY_CASE
        ,GREATEST(x,y,z) AS GREATEST_BY_FUNC
    FROM samples
    ;
    ```
    </details>
---

+ 問2. costが1000以上のものは10%増加, costが10000以上のものは10%減少で更新してください. そのあと表示してください

    samplesテーブル
    | id | cost |
    |:-:|-:|
    | A | 100  |
    | B | 1000  |
    | C | 10000  |
    | D | 100000  |
    | E | 9000  |
    | F | 11000  |
    | G | 9500  |
    | H | 10500  |

    ↓

    期待結果

    | id | cost |
    |:-:|-:|
    | A | 100|
    | B | 1100 |
    | C | 9000  |
    | D | 90000  |
    | E | 9900 |
    | F | 9900  |
    | G | 10450 |
    | H | 9450  |
    
    + [オンライン実行環境(sqlfiddle)](https://sqlfiddle.com/sql-server/online-compiler?id=78a54b9b-fdf5-48dc-9d41-20bc5e2807a0)
    <details><summary>解答</summary>

    ```sql
    UPDATE samples
    	SET cost = CASE WHEN 1000 <= cost AND cost < 10000 THEN cost * 1.1 WHEN 10000 <= cost THEN cost * 0.9 ELSE cost END
    ;
    ```
    </details>

---
+ 問3. class別毎の開始時期(stage=1)と末期時期(stage=3)の残高を求めてください

    samplesテーブル
    | ID | class | stage | balance |
    |:-:|:-:|:-:|:-:|
    |A| X| 1| 10|
    |B| X| 2| 20|
    |C| X| 3| 40|
    |D| Y| 1| 80|
    |E| Y| 2| 160|
    |F| Y| 3| 320|
    |G| Z| 1| 640|
    |H| Z| 2| 1280|

    ↓

    期待結果

    | class | beginning_of_balance | end_of_balance |
    |:-:|-:|-:|
    | X | 10 | 40 |
    | Y | 80 | 320 |
    | Z | 640 | 0 |

    + [オンライン実行環境(sqlfiddle)](https://sqlfiddle.com/sql-server/online-compiler?id=cb936484-8066-4171-8e6a-cb976087958e)

    <details><summary>解答</summary>

    ```sql
    SELECT
        class
        ,SUM(CASE WHEN stage = '1' THEN balance ELSE 0 END) as beginning_of_balance
        ,SUM(CASE WHEN stage = '3' THEN balance ELSE 0 END) as end_of_balance
    FROM samples
    GROUP BY class
    ;
    ```
    </details>

---

+ 問4. 縦軸に教科名, 横軸が(4月, 5月, 6月)で対応している月に○が記載されている表を作成してください

    subjectsテーブル
    | id | subject |
    |:-:|:-:|
    | 1  | Japanese  |
    | 2  | Math  |
    | 3  | Science  |
    | 4  | English  |

    coursesテーブル
    | month | course_id |
    |:-:|:-:|
    | 201404  | 1  |
    | 201404  | 3  |
    | 201404  | 4  |
    | 201405  | 4  |
    | 201406  | 2  |
    | 201406  | 4  |

    ↓

    期待結果
    | subject | 4月 | 5月 | 6月 |
    |:-:|:-:|:-:|:-:|
    | Japanese | o | x | x |
    | Math     | x | x | o |
    | Science  | o | x | x |
    | English  | o | o | o |

    + [オンライン実行環境(sqlfiddle)](https://sqlfiddle.com/sql-server/online-compiler?id=8b6f795a-323e-4925-8258-232a86595d08)
    <details><summary>解答</summary>

    ```sql
    SELECT subject
    	,CASE WHEN SUM(CASE WHEN master.id = courses.course_id AND month = '201304' THEN 1 ELSE 0 END) = 1 THEN "o" ELSE "×" END AS "4月"
    	,CASE WHEN SUM(CASE WHEN master.id = courses.course_id AND month = '201305' THEN 1 ELSE 0 END) = 1 THEN "o" ELSE "×" END AS "5月"
    	,CASE WHEN SUM(CASE WHEN master.id = courses.course_id AND month = '201306' THEN 1 ELSE 0 END) = 1 THEN "o" ELSE "×" END AS "6月"
    FROM master
    LEFT JOIN courses
    ON id = course_id
    GROUP BY subject
    ;
    ```
    </details>