はじめに
MySQL 8.0から使えるようになったWindow関数
。私自身、「GROUP BY
や一時テーブル機能の拡張のようなものかな?」くらいにしか思っておりませんでした。
しかし、今回の「【あなたの】はじめてのMySQL」記事投稿キャンペーンをきっかけに調べてみたところ、これが非常に便利そう。
そこで本記事では、私が実際にWindow関数を使ってみて感じた利便性と、その実行過程を共有します。
Window関数とは
Window関数は、一言で言うと 「データをグループ化せずに、特定の範囲の中で計算を行う関数」 です。
GROUP BY
と何が違う?
GROUP BY
はデータを集計するために使われ、結果の行数がグループの数だけ減ります。それに対し、Window関数はデータをグループ化せず、元の行数を維持したまま行ごとに計算を行います。これにより、集計結果と元のデータを同時に見れるのが大きな違いです。
特徴 | GROUP BY | Window関数 |
---|---|---|
行の扱い | グループで集計され、結果の行数が減る | 各行はそのまま維持され、結果の行数は減らない |
計算範囲 | グループ全体に対する集計のみ | 指定した「ウィンドウ」内での集計・比較・順位付け |
簡単に言うと、GROUP BY
がデータを「まとめる」機能なら、Window関数はデータを「各行ごとに分析する」機能です。
GROUP BY
では難しかった分析をWindow関数でやってみる
ここからは実践です! サンプルデータとして、各旅行者が訪れた国と訪問日を扱うテーブルを使います。
▼例で使用するテーブル:travel_history
traveler_id | country | visit_date |
---|---|---|
101 | 日本 | 2023-03-10 |
101 | 韓国 | 2023-01-01 |
101 | タイ | 2023-05-20 |
102 | アメリカ | 2023-02-05 |
102 | カナダ | 2023-04-10 |
INSERT文
CREATE TABLE travel_history (
traveler_id INT NOT NULL,
country VARCHAR(50) NOT NULL,
visit_date DATE NOT NULL
);
INSERT INTO travel_history (traveler_id, country, visit_date) VALUES
(101, '日本', '2023-03-10'),
(101, '韓国', '2023-01-01'),
(101, 'タイ', '2023-05-20'),
(102, 'アメリカ', '2023-02-05'),
(102, 'カナダ', '2023-04-10');
このテーブルを使って、「各旅行者が訪れた国を、訪問順に何番目の国か知りたい」 といったランキング情報を取得してみます。
しかし、、、GROUP BY
だけだと、traveler_id
ごとの総訪問国数は出せても、個々の訪問に順番を振ることはできません。
そこでWindow関数の出番です!
Window関数で実践:ROW_NUMBER()
と PARTITION BY
句
-
ROW_NUMBER()
関数- 指定されたグループ内で、各行にユニークな連番(順位)を割り振る Window関数です。同じ値を持つ行があっても、それぞれに異なる番号が振られます。
-
PARTITION BY
句-
ROW_NUMBER()
がどの範囲で連番を振るかを指定します。PARTITION BY
は、データを特定の列(例えばtraveler_id
)で論理的にグループ分けしますが、GROUP BY
とは違って 結果の行数を減らしません。各グループ内の行を個別に保持したまま、そのグループ内で計算を行います。
-
SELECT
traveler_id,
country,
visit_date,
ROW_NUMBER() OVER (PARTITION BY traveler_id ORDER BY visit_date ASC) AS visit_order_no
FROM
travel_history;
-
ROW_NUMBER() OVER (~~~)
- これがウィンドウ関数の構文です。
-
PARTITION BY traveler_id
- ここで「旅行者IDごとに」データを区切っています。これにより、
traveler_id
が異なる行では、visit_order_no
が1から振り直されます。
- ここで「旅行者IDごとに」データを区切っています。これにより、
-
ORDER BY visit_date ASC
-
PARTITION BY
で区切られた各旅行者の中で、visit_date
(訪問日)が古い順に並べ替えを行い、その順番で連番を振ります。
-
▼実行結果
traveler_id | country | visit_date | visit_order_no |
---|---|---|---|
101 | 韓国 | 2023-01-01 | 1 |
101 | 日本 | 2023-03-10 | 2 |
101 | タイ | 2023-05-20 | 3 |
102 | アメリカ | 2023-02-05 | 1 |
102 | カナダ | 2023-04-10 | 2 |
このように、各行を維持したまま、旅行者ごとの訪問順という情報が簡単に追加できます。
まとめ
MySQLのウィンドウ関数は、従来の GROUP BY
では複雑なサブクエリや自己結合が必要だったような、「グループ内の各行に対するランキング」 といった分析を、シンプルかつ効率的に実現できる機能です。
今回の内容は数あるWindow関数の中のごく一部ですが、まずはWindow関数が「GROUP BY
では難しい、各行に注目した分析ができる」ということを理解いただけたなら幸いです。