CodeGym /コース /SQL SELF /ウィンドウ関数と集約関数の比較: GROUP BY vs PARTITI...

ウィンドウ関数と集約関数の比較: GROUP BY vs PARTITION BY

SQL SELF
レベル 30 , レッスン 0
使用可能

パッと見だと、ウィンドウ関数と集約関数ってどっちもデータ分析や処理に使う似たようなツールに見えるよね。どっちも合計や平均、ランキングとかの計算ができる。でも、実は本質的に違うんだ。詳しく見てみよう!

集約関数(GROUP BY

集約関数はこんな感じで動くよ:

  • 指定したカラムで行をグループ化する。
  • グループ化した後、各グループは結果の1行になる
  • 例:各地域ごとの売上合計を知りたいとき。
SELECT region, SUM(sales) AS total_sales
FROM sales_data
GROUP BY region;

ポイント: GROUP BYはデータを「圧縮」する。グループ化したら、そのグループに入ってた行は消えて、集計結果だけが残るよ。

ウィンドウ関数(PARTITION BY

ウィンドウ関数は逆に:

  • 元のデータ構造をそのまま保つ(行が消えたり圧縮されたりしない!)。
  • 「ウィンドウ」=論理的に区切ったグループ内で計算できる。

例:各都市の売上が、その都市が属する地域の合計売上に対してどれくらいの割合か知りたい。でも全データはそのまま残したい。

SELECT
    region,
    city,
    sales,
    SUM(sales) OVER (PARTITION BY region) AS total_sales_by_region
FROM sales_data;

ポイント:ウィンドウ関数を使っても行は消えない。各行に新しい計算結果が追加されるだけ。

例:SUM()GROUP BY vs SUM()PARTITION BY

違いをもっとわかりやすくするために、SUM()が両方でどう動くか見てみよう。例えば、sales_dataテーブルがこんな感じだとする:

region city sales
North CityA 100
North CityB 150
South CityC 200
South CityD 250

GROUP BYで合計する場合

各地域ごとの売上合計を知りたい:

SELECT region, SUM(sales) AS total_sales
FROM sales_data
GROUP BY region;

結果はこうなる:

region total_sales
North 250
South 450

何が起きたか: regionでグループ化されて、各グループが売上合計1行に「圧縮」された。

PARTITION BYで合計する場合

今度はウィンドウ関数で同じことをやってみる:

SELECT
    region,
    city,
    sales,
    SUM(sales) OVER (PARTITION BY region) AS total_sales_by_region
FROM sales_data;

結果:

region city sales total_sales_by_region
North CityA 100 250
North CityB 150 250
South CityC 200 450
South CityD 250 450

何が起きたか: PARTITION BYは行を「圧縮」しなかった。その代わり、特定のウィンドウ内(各地域ごと)で合計を計算した。

GROUP BYPARTITION BY、どっちを使う?

GROUP BY: 最終レポートに向いてる

GROUP BYはデータ量を減らして、グループごとの最終結果が欲しいときに便利。例えば:

  • 月ごとの売上合計。
  • 商品カテゴリごとの注文数カウント。

例:

SELECT category, COUNT(*) AS total_orders
FROM orders
GROUP BY category;

PARTITION BY: 分析や詳細チェックに最適

PARTITION BYは、全データを残したまま、各行ごとに追加計算したいときに使う。例えば:

  • 各商品のカテゴリ内での売上割合を出す。
  • 各グループ内で行に連番を振る。

売上割合の計算例:

SELECT
    category,
    product,
    sales,
    ROUND(
        (sales * 100.0) / SUM(sales) OVER (PARTITION BY category),
        2
    ) AS sales_percentage
FROM sales_data;

例:複数のウィンドウ関数を使う

ウィンドウ関数の強みの一つは、いろんな計算を一気にできること。例えば:

SELECT
    region,
    city,
    sales,
    SUM(sales) OVER (PARTITION BY region) AS total_sales,
    RANK() OVER (PARTITION BY region ORDER BY sales DESC) AS sales_rank
FROM sales_data;

結果:

region city sales total_sales sales_rank
North CityB 150 250 1
North CityA 100 250 2
South CityD 250 450 1
South CityC 200 450 2

GROUP BYよりウィンドウ関数が優れてるポイント

元データをそのまま残せる: GROUP BYは行を「圧縮」しちゃうけど、ウィンドウ関数ならテーブルの構造をそのままキープできる。

1つのクエリで複数計算できる: PARTITION BYORDER BYのパラメータを変えて、いろんなウィンドウ関数を同時に使える。

分析の柔軟性: ウィンドウ関数なら累積合計、ランキング、割合計算など、いろんな分析が自由自在!

柔軟性の例

いくつかの関数を組み合わせてみよう:

SELECT
    region,
    city,
    sales,
    SUM(sales) OVER (PARTITION BY region) AS total_sales,
    AVG(sales) OVER (PARTITION BY region) AS avg_sales,
    RANK() OVER (PARTITION BY region ORDER BY sales DESC) AS rank
FROM sales_data;

結果:

region city sales total_sales avg_sales rank
North CityB 150 250 125.0 1
North CityA 100 250 125.0 2
South CityD 250 450 225.0 1
South CityC 200 450 225.0 2

制限とよくあるミス

よくあるミスの一つは、「データを圧縮したいときにPARTITION BYを使っちゃう」こと。例えば、本当はこう書くべきなのに:

SELECT region, SUM(sales) AS total_sales
FROM sales_data
GROUP BY region;

こう書いちゃう人がいる:

SELECT
    region,
    SUM(sales) OVER (PARTITION BY region) AS total_sales
FROM sales_data;

でもこれだと全行が返ってきて、データ量は減らない(それが欲しい結果じゃない場合も多い)。

これで、GROUP BYとウィンドウ関数、どっちを使うべきかバッチリわかったね。ハンマーとドライバーの使い分けみたいなもんで、どっちも釘は打てるけど…やり方が違うんだ。

コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION