メインコンテンツへ
データベースデータベース応用

SQLウィンドウ関数に関する次のクエリの動作として、最も適切なものはどれか。 SELECT name, dept, salary, ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC) AS rn, RANK() OVER (PARTITION BY dept ORDER BY salary DESC) AS rk FROM employees;

ア.ROW_NUMBER()とRANK()は同義であり、rnとrkは常に完全に一致する。
イ.ROW_NUMBER()はPARTITION BY句を無視して全テーブルに対する通し番号を振り、RANK()のみPARTITION BYで部署ごとに区切られる。
ウ.ROW_NUMBER()は同値タイに同じ番号を振り、RANK()は順位を飛ばさず1,2,2,3と詰めて返す。
エ.ROW_NUMBER()は部署内でORDER BYに従い1,2,3,…と必ず一意の連番(同値タイでも別番号)を振り、RANK()は同値タイ(同じsalary)に同順位を与え次の順位を「タイの数だけ飛ばす」(例:1,2,2,4)。一方DENSE_RANK()は同値同順位だが順位を詰める(例:1,2,2,3)。正解

解説

3つのランク関数は「同点プレーヤーの扱い」で性格が分かれます。ROW_NUMBERは「同点でも強制的に順番を決める几帳面な審判」、RANKは「同点は同順位、その分次を飛ばす公式競技ルール」、DENSE_RANKは「同点は同順位、でも順位は詰めるダンスコンテスト方式」。

なぜ エ が正解か

エが正解。SQL標準のウィンドウ関数で、PARTITION BY dept ORDER BY salary DESC を共有する場合の挙動:(1)ROW_NUMBER()は部署ごとに給与降順で1,2,3,…と必ず一意の連番を振る(同じsalaryが2件あっても優先順は処理系依存だが番号は別)、(2)RANK()は同値タイに同順位を与え、その分次の順位を飛ばす(例:給与10,10,8なら順位は1,1,3)、(3)DENSE_RANK()は同値同順位かつ順位を飛ばさず詰める(例:1,1,2)。3つの使い分けはタイをどう扱いたいかで決まる。

なぜ ア は間違いか

両者は明確に異なる関数。同値タイがあるテーブルではrnとrkは異なる値を返す。「常に一致」は誤り。

なぜ イ は間違いか

ROW_NUMBER()もPARTITION BY句を尊重する。両関数ともPARTITION BYで指定された各グループ内で1から番号を振り直す。一方だけ無視するという挙動はない。

なぜ ウ は間違いか

説明が逆。ROW_NUMBER()は同値でも別番号(必ず一意の連番)を振る。「同値タイに同じ番号を振り、順位を詰める」のはDENSE_RANK()の挙動であり、ROW_NUMBER/RANKの説明として誤り。

出典: AI生成問題(学習用)