SQLで集計を行う際に、行を束ねるのではなくて、全ての行に追加で集計結果のデータを持たせたい場合はありませんか?
指定したカラムごとで行を束ねたい場合はGROUP BY句
を使えば実現できますが、行を束ねずに集計したい場合は別の方法を用いる必要があります。
それが、今回紹介する分析関数のOVER句
です。
本記事では分析関数とは何かから始まり、OVER句
の具体的な使い方まで解説します。
目次
分析関数とは
SQLの分析関数は、グルーピングされたデータの集計結果を一つ一つの行に持たせることができる文法です。
集約関数との違い
分析関数はグルーピングされたデータに対して処理をするという点において、SUM
やCOUNT
のような集約関数と考え方は似ています。
集約関数との決定的な違いは、集約関数は同一の値を持つ行をグルーピングして結果を取得するという点です。例えば、下記の図のようにCOUNT関数
を用いてaddress
ごとの数をカウントしようとすると、同じaddress
の値を持つ行はグルーピングされます。
一方で、分析関数は行ごとで集計したデータを取得できます。下記の図のように、行の数は変わらないままCOUNT関数の結果を取得することができるのです。
では次に、分析関数を実現するためのクエリの書き方を見ていきましょう。
SQLのOVER句とは
SQLで分析関数を使用するにはOVER句
を使います。
OVER句
を使った基本フォーマットが以下になります。
OVER (PARTITION BY カラム名 ORDER BY カラム名)
PARTITION BY
PARTITION BY
はGROUP BY
のようなイメージで、指定した列でグルーピングを行います。GROUP BY
はクエリ全体に対してグルーピングを行いますが、PARTITION BY
は特定の列に対してのみ処理が行えます。
先ほどの例のように、address
ごとの人数をカウントして各行にその結果を持たせたい場合は、下記のようなクエリを書きます。
COUNT(*) OVER (PARTITION BY address)
ORDER BY
ORDER BY
は並び替えを行うことができる文法です。OVER句
の中でもORDER BY
を使うことができます。集計結果を並び替えたい場合はORDER BY
も併せて使いましょう。
例えば、集計結果が多い順に並べ替えたい場合は、下記のようにORDER BY
を指定するといった具合です。
COUNT(*) OVER (PARTITION BY address ORDER BY COUNT(*) DESC)
OVER句を使ってクエリを作成してみよう
ここからは具体的な使用例を見て、理解を深めていきましょう。
まずは、サンプルデータとして以下のusersテーブルを用意します。
サンプルデータ
id | name | age | address |
---|---|---|---|
1 | 山田 | 25 | 東京都 |
2 | 鈴木 | 34 | 神奈川県 |
3 | 佐藤 | 28 | 神奈川県 |
4 | 大野 | 46 | 大阪府 |
5 | 小池 | 56 | 東京都 |
6 | 近藤 | 24 | 東京都 |
7 | 佐々木 | 38 | 大阪府 |
8 | 宮田 | 32 | 福岡県 |
9 | 田中 | 51 | 大阪府 |
10 | 木村 | 28 | 神奈川県 |
お題
usersテーブルに新しいカラム(avg_age_by_address)を作成して、都道府県ごとの平均年齢を追加してください
クエリ
SELECT
id,
name,
address,
age,
AVG(age) OVER (PARTITION BY address) AS avg_age_by_address
FROM users
ORDER BY id ASC;
ポイントは6行目です。
まず、平均年齢を求めるAVG関数
を使用して、AVG(age)
とします。加えて、今回は都道府県ごとの平均年齢を算出する必要があるため、OVER句
とPARTITION BY
を使って都道府県でグルーピングします。
この時、GROUP BY句
を使ってしまうとクエリ全体でグルーピングされてしまうため、AVG(age)
に対してのみ処理ができるOVER句
を使います。
これによって、全ての行に対して都道府県ごとの平均年齢を持たせるカラムを作成することができました。
実行結果
id | name | address | age | avg_age_by_address |
---|---|---|---|---|
1 | 山田 | 東京都 | 25 | 35 |
2 | 鈴木 | 神奈川県 | 34 | 30 |
3 | 佐藤 | 神奈川県 | 28 | 30 |
4 | 大野 | 大阪府 | 46 | 45 |
5 | 小池 | 東京都 | 56 | 35 |
6 | 近藤 | 東京都 | 24 | 35 |
7 | 佐々木 | 大阪府 | 38 | 45 |
8 | 宮田 | 福岡県 | 32 | 32 |
9 | 田中 | 大阪府 | 51 | 45 |
10 | 木村 | 神奈川県 | 28 | 30 |
avg_age_by_addressカラム
が新規作成され、全ての行において都道府県別の平均年齢を取得することができました。
内容のまとめ
- SQLの分析関数とはグルーピングされたデータの集計結果を一つ一つの行に持たせることができる文法
- 集約関数は同一の値を持つ行をグルーピングした結果を取得しますが、分析関数も併用することで、全ての行に対してグルーピングした結果を取得できるようになる
- SQLの分析関数には
OVER句
を用いる OVER句
を使った基本フォーマットはOVER (PARTITION BY カラム名 ORDER BY カラム名)