SQLアタマアカデミー
第2回 更新なんてこわくない! (3)列から行への更新
列から行への更新
今度は先ほどの逆パターンを考えます。つまり,表6のように列持ちのテーブルの情報を行持ちのテーブルへ更新するのです。更新後のScoreRowsテーブルは表7のようになります。
表6 サンプルテーブル(行から列へ)
ScoreCols:列持ち
| student_id (学生ID) | score_en (点数- 英) | score_nl (点数- 国) | score_mt (点数- 数) |
|---|---|---|---|
| A001 | 100 | 58 | 90 |
| B002 | 77 | 60 | |
| C003 | 52 | 49 | |
| D004 | 10 | 70 | 100 |
![]()
ScoreRows:行持ち
| student_id (学生ID) | subject (教科) | score (点数) |
|---|---|---|
| A001 | 英語 | |
| A001 | 国語 | |
| A001 | 数学 | |
| B002 | 英語 | |
| B002 | 国語 | |
| C001 | 英語 | |
| C003 | 国語 | |
| C003 | 社会 |
表7 ScoreRows:行持ち(更新後)
| student_id (学生ID) | subject (教科) | score (点数) |
|---|---|---|
| A001 | 英語 | 100 |
| A001 | 国語 | 58 |
| A001 | 数学 | 98 |
| B002 | 英語 | 77 |
| B002 | 国語 | 60 |
| C001 | 英語 | 52 |
| C003 | 国語 | 49 |
| C003 | 社会 |
「C003」の社会の情報はScoreColsテーブルにありませんので,NULLのままです。また「C004」は更新先のScoreRowsテーブルにいないので,更新しても現れません。
今度は,各生徒について更新対象となる行を,subjectの値によって分岐させることになります。したがって,SET句のサブクエリ内で次のようにCASE式を使った分岐を行えばOKです(リスト8)。score_en,score_nl,score_mtという3つの列を1つの列にたたみこむようなイメージを持ってもらえばわかりやすいでしょう。
リスト8 列→行の更新SQL
UPDATE ScoreRows
SET score = (SELECT CASE ScoreRows.subject
WHEN '英語' THEN score_en
WHEN '国語' THEN score_nl
WHEN '数学' THEN score_mt
ELSE NULL
END
FROM ScoreCols
WHERE student_id = ScoreRows.student_id);
演習問題
さて,それではこの「列から行への更新」に関して,演習問題を2つ出しておきましょう。前回同様,解答はサポートサイトから確認してください。
問題1. いまScoreRowsテーブルのscoreはNULLを許可していますが,この列にNOT NULL制約を付けます(初期値は全行「0」で統一)。その場合でも列から行へ変換できるUPDATE文を考えてください(ヒント:リスト8をそのまま実行すると,「C003」の社会をNULLに更新しようとしてエラーになります)。
問題2. リスト8では,もともと更新先のテーブルに存在しない「D004」は更新後のテーブルにも存在しないままでした。そこで,この生徒の情報も追加できるようなSQLを考えてください。
SQL, データベース, 更新, ScoreColsテーブル, NULL
SQLアタマアカデミー
- 最終回 OLAP関数で強力な統計処理を実現!―手続き型から理解するSQL (5)集合指向と手続き型
- 最終回 OLAP関数で強力な統計処理を実現!―手続き型から理解するSQL (4)OLAP関数と集約関数を組み合わせる
- 最終回 OLAP関数で強力な統計処理を実現!―手続き型から理解するSQL (3)OLAP専用関数
- 最終回 OLAP関数で強力な統計処理を実現!―手続き型から理解するSQL (2)OLAP関数の基本構文
- 最終回 OLAP関数で強力な統計処理を実現!―手続き型から理解するSQL (1)OLAP関数とは何か
- 第10回 結合大全 (5)非等値結合
- 第10回 結合大全 (4)自己結合
- 第10回 結合大全 (3)外部結合
- 第10回 結合大全 (2)内部結合
- 第10回 結合大全 (1)クロス結合

