9
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

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から振り直されます。
  • 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 では難しい、各行に注目した分析ができる」ということを理解いただけたなら幸いです。

9
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?