SQLアタマアカデミー

第2回 更新なんてこわくない! (3)列から行への更新

この記事を読むのに必要な時間:およそ 1 分

列から行への更新

今度は先ほどの逆パターンを考えます。つまり,表6のように列持ちのテーブルの情報を行持ちのテーブルへ更新するのです。更新後のScoreRowsテーブルは表7のようになります。

表6 サンプルテーブル(行から列へ)
ScoreCols:列持ち

student_id
(学生ID)
score_en
(点数- 英)
score_nl
(点数- 国)
score_mt
(点数- 数)
A0011005890
B0027760 
C0035249 
D0041070100

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を考えてください。

著者プロフィール

ミック

SI企業に勤務するDBエンジニア。主にデータウェアハウス業務に従事している。自身のサイト「リレーショナル・データベースの世界」でデータベースとSQLについての技術情報を公開している。『Web+DB Press』で「SQLアタマアカデミー」を連載中。

著書:『達人に学ぶ SQL徹底指南書』(翔泳社、2008)訳書:J.セルコ『SQLパズル 第2版』(翔泳社、2007)

SQLアタマアカデミー:サポートページ

コメント

コメントの記入