【うぃんどうかんすう】
ウィンドウ関数 とは?
💡 行をまとめずに「周辺の行を見ながら計算する」SQL関数
📌 このページのポイント
- OVER句で計算範囲(ウィンドウ)を指定し、行をグループ化せずに集計できる
- ROW_NUMBER、RANK、DENSE_RANKで順位付けができる
- SUM() OVER()で累積合計、AVG() OVER()で移動平均が計算できる
- PARTITION BYでグループ単位の計算、ORDER BYで行の順序を指定する
ウィンドウ関数ってGROUP BYとどう違うの?
具体的にどう書くの?
「SELECT name, salary, RANK() OVER (ORDER BY salary DESC) as rank FROM employees」で全社員の給与ランキングが出る。「SUM(sales) OVER (PARTITION BY dept ORDER BY month)」なら部署ごとの月別累積売上が計算できる。OVER句が「ウィンドウ(計算範囲)」を定義するよ。
ROW_NUMBERとRANKとDENSE_RANKの違いは?
同じ値が2つあるときの挙動が違う。ROW_NUMBERは必ず連番(1,2,3)で同値でも順番が付く。RANKは同値を同順位にして次の順位を飛ばす(1,1,3)。DENSE_RANKは同値を同順位にするけど次の順位を飛ばさない(1,1,2)。
ウィンドウ関数ってパフォーマンスは大丈夫?
ウィンドウ関数はソートが必要だから、大量データだと負荷が高い。特にPARTITION BYとORDER BYが複雑になると、内部でソートが多重に走ることがある。さらに厄介なのはフレーム指定(ROWS BETWEEN〜)で、「ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW」と「RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW」は似ているようで重複値の扱いが全然違う。ROWSは物理的な行数で範囲を決め、RANGEは値の範囲で決める。ここの理解が曖昧だと集計結果がずれるのに、エラーにはならないから気づきにくいんだよね。
まとめ:ざっくりこれだけ覚えればOK!
ウィンドウ関数って出てきたら「GROUP BYで行をまとめずに、各行で周辺の行を参照しながら計算できる仕組み」と思えばだいたいOK!
📖 おまけ:英語の意味
「Window Function」 = 窓(Window)関数(Function)
💬 各行から見える範囲(窓=ウィンドウ)を定義して、その範囲で計算するイメージ