以降も提出を行うことができますが、順位集計には反映されません。
問題1~4では試験コードが'T00001'のデータしか用意されていません。
そのため、試験コードの条件指定がなくても正解できるようになっています。
【問題1】副問合せの結果で絞り込み1
最初のUPDATE文では合格者のデータを更新しています。
副問合せで平均点を集計し、WHERE句で平均点以上であるかを判定しています。
その後、更新されなかった残りのデータを不合格として更新しています。
-- 合格者のデータを更新
UPDATE total_scores
SET passed = TRUE
WHERE total_score >= (
SELECT AVG(total_score)
FROM total_scores
);
-- 不合格者のデータを更新
UPDATE total_scores
SET passed = FALSE
WHERE passed IS NULL;
副問合せをFROM句で実行し、CASE文を利用して更新することもできます。
UPDATE total_scores
SET passed =
CASE
WHEN total_score >= sub.avg THEN TRUE
ELSE FALSE END
FROM (
SELECT AVG(total_score) AS avg
FROM total_scores
) AS sub
【問題2】分析関数の結果で更新1
RANK
は分析関数(ウィンドウ関数)のひとつです。
続くOVER
内でPARTITION
やORDER
を使用して、データを集計することができます。
SELECT
student_code,
RANK() OVER(ORDER BY total_score DESC) AS ranking
FROM total_scores
上記ではtotal_score
の降順に順位を算出しています。
本問題では試験コードが'T00001'のデータしか用意されいませんが、PARTITION BY test_code
と指定することで、試験ごとに区切ったうえで順位を算出することもできます。
あとは上記の処理をFROM句内の副問合せで実行し、WHERE句で結合条件を指定します。
UPDATE total_scores AS ts
SET ranking = sub.ranking
FROM (
SELECT
student_code,
RANK() OVER(ORDER BY total_score DESC) AS ranking
FROM total_scores
) AS sub
WHERE ts.student_code = sub.student_code
【問題3】副問合せの結果で絞り込み2
最初のUPDATE文で各科目の合格者のデータを更新しています。
FROM句内で副問合せを実行し、WHERE句で結合条件を指定しています。
今回は科目ごとに平均点を集計したいのでGROUP BY subject_code
を指定します。
その後、更新されていない残りのデータを不合格として更新しています。
-- 合格者のデータを更新
UPDATE scores AS s
SET passed = TRUE
FROM (
SELECT
subject_code,
AVG(score) AS avg
FROM scores
GROUP BY subject_code
) AS sub
WHERE s.subject_code = sub.subject_code
AND s.score >= sub.avg;
-- 不合格者のデータを更新
UPDATE scores
SET passed = FALSE
WHERE passed IS NULL;
良くない例
UPDATE scores AS s1
SET passed = TRUE
WHERE s1.score >= (
SELECT AVG(score)
FROM scores AS s2
WHERE s1.subject_code = s2.subject_code
);
UPDATE scores
SET passed = FALSE
WHERE passed IS NULL;
良くない例
UPDATE scores AS s1
SET passed =
CASE
WHEN s1.score >= (
SELECT AVG(score)
FROM scores AS s2
WHERE s1.subject_code = s2.subject_code
) THEN TRUE
ELSE FALSE
END
WHERE句やSET句で相関副問合せを実行することもできます。
しかし、これらの方法ではパフォーマンスが著しく悪化してしまい、TLE(Time Limit Exceeded: 時間制限超過)の原因となります。
【問題4】分析関数の結果で更新2
解答例ではPARTITION
付きでRANK
関数を使用しています。
scores
テーブルに対してsubject_code
でデータを区切りったうえでscore
の降順で順位を算出します。
SELECT
student_code,
subject_code,
RANK() OVER(PARTITION BY subject_code ORDER BY score DESC) AS ranking
FROM scores
上記の処理をFROM句内の副問合せで実行し、student_code
およびsubject_code
を条件として結合します。
UPDATE scores AS s
SET ranking = sub.ranking
FROM (
SELECT
student_code,
subject_code,
RANK() OVER(PARTITION BY subject_code ORDER BY score DESC) AS ranking
FROM scores
) AS sub
WHERE s.student_code = sub.student_code
AND s.subject_code = sub.subject_code