分析関数(OVER句,WINDOW句)
分析関数はグループ内の指定された範囲で集計を行い、結果を集計元の各行に戻すことができます。
分析関数はSQLとしては比較的新しい機能で、ウィンドウ(Window)関数とも呼ばれます。。
サブクエリーを複数組み合わせなければできなかったものが比較的簡単なSQL文で実現できるようになります。
分析関数とは
分析関数はグループ内の指定された範囲で集計し、集計元の各行に戻すことができます。
また、分析関数はレコードの順序の概念を持つので、指定行位置のデータを取得することができます。
簡潔なSQL文で複雑な分析処理を従来よりも高速に処理可能となります。
OVER句に以下を指定することで集計範囲を各種指定できます。
PARTITION BY ・・・ グループ分け
ORDER BY ・・・ 順序指定
ROWS BETWEEN ・・・ レコード範囲
さらにOVER句の前にFILTER句を指定することで、条件を満たしたレコードのみで処理を行うこともできます。
SUM関数 ・・・ 合計
AVG関数 ・・・ 平均
MAX関数 ・・・ 最大
MIN関数 ・・・ 最小
RANK関数 ・・・ 順位
DENSE_RANK関数 ・・・ 順位
LAG関数 ・・・ n個前
LEAD関数 ・・・ n個後
OVER句
UNBOUNDED PRECEDING ・・・ 最初のレコード
n PRECEDING ・・・ n個前のレコード
CURRENT ROW 現在のレコード
n FOLLOWING ・・・ n個後のレコード
UNBOUNDEE FOLLOWING ・・・ 最後のレコード
RANGEはORDER BYで指定したカラムの値で範囲指定します。
「RANGE must use only UNBOUNDED or CURRENT ROW」
このエラーが発生しました。
UNBOUNDED または CURRENTだけを指定すると確かに動作しますが、
これしか使えないとすると、用途がかなり限定されてしまいます。
このような事情があるので、今回は具体的な解説を省略しています。
WINDOW句
使い方としては、WITH句と同様に考えると分かり易いと思います。
分析関数 OVER(・・・)
分析関数 OVER ウインドウ名
・・・
FROM ・・・
WINDOW ウインドウ名 AS (・・・)
少なくともSQLiteにおいては、上記のように単純な使い方としてとらえて良いでしょう。
SELECT ・・・
FROM ・・・
WHERE ・・・
GROUP BY ・・・
WINDOW ・・・
ORDER BY ・・・
FILTER句
分析関数の使用例
分析関数の使用例:グループの最大/最小/平均を明細に出力
以下の処理順となります。
・MAX,MIN,AVG
・元の明細と列出力
サブクエリだけのSQL
SELECT
T.code,T.sales_date,T.item_code
,T.item_count * T.item_price AS item_amount
,TT.max_amount,TT.min_amount,TT.avg_amount
FROM t_sales T
INNER JOIN
(SELECT code,item_code
,MAX(item_count * item_price) AS max_amount
,MIN(item_count * item_price) AS min_amount
,AVG(item_count * item_price) AS avg_amount
FROM t_sales
GROUP BY code,item_code) TT
ON T.code = TT.code AND T.item_code = TT.item_codeOVER句を使ったSQL
SELECT
code,sales_date,item_code
,item_count * item_price AS item_amount
,MAX(item_count * item_price) OVER(PARTITION BY code,item_code) AS max_amount
,MIN(item_count * item_price) OVER(PARTITION BY code,item_code) AS min_amount
,AVG(item_count * item_price) OVER(PARTITION BY code,item_code) AS avg_amount
FROM t_sales
OVER句+WINDOW句
SELECT
code,sales_date,item_code
,item_count * item_price AS item_amount
,MAX(item_count * item_price) OVER PART AS max_amount
,MIN(item_count * item_price) OVER PART AS min_amount
,AVG(item_count * item_price) OVER PART AS avg_amount
FROM t_sales
WINDOW PART AS (PARTITION BY code,item_code)
分析関数の使用例:FILTER句で条件指定
そこで、以下では金額が0は集計から除外しています。
SELECT
code,sales_date,item_code
,item_count * item_price AS item_amount
,AVG(item_count * item_price)
FILTER(WHERE item_count * item_price <> 0)
OVER PART AS item_avg
FROM t_sales
WINDOW PART AS (PARTITION BY code,item_code)分析関数の使用例:明細にレコード番号(連番)を振る
以下の処理順となります。
・金額降順で並べ替え
・1から順に通し番号を振る
同じ金額かどうかは関係なく出力順通りの通し番号にします。
WITH TT AS
(SELECT *, 1 AS nn,item_count * item_price AS item_amount
FROM t_sales)
SELECT
SUM(nn) OVER pre AS No
,code,sales_date,item_code,item_amount
FROM TT
WINDOW pre AS
(ORDER BY item_count * item_price DESC
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
LIMIT 100ROW_NUMBERまたはROWNUM等を使う事で、簡単にレコード番号を取得できます。
SQLiteにはこの機能がないため、サンプル例題としています。
分析関数の使用例:前回販売日を取得
ただし、code,item_code,sales_dateが同一のレコードが複数あることが前提ですので、
単純に直前のレコード取得では、意図した結果になりません。
RANGEでPRECEDINGを指定できれば、かなり簡単に取得できるはずでした。
以下のSQLは代替えとして作成したものになりますが、かなり複雑なSQLとなってしまいました。
したがってこのSQLは、あくまで練習用SQLとしてお考え下さい。
それでも、分析関数を使っているのでこの程度で済んでいますが、使わなければさらに複雑なSQLになるはずです。
先頭日付では、前回の販売日はnullになります。
その後は、これをJOINしているだけになります。
WITH TT AS
(SELECT code,item_code,sales_date
FROM t_sales
GROUP BY code,item_code,sales_date)
SELECT
T.code,T.item_code,T.sales_date,MT.last_date
FROM t_sales T
INNER JOIN
(SELECT
code,item_code,sales_date
,MAX(sales_date) OVER pre AS last_date
FROM TT
WINDOW pre AS
(PARTITION BY code,item_code
ORDER BY code,item_code,sales_date
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING)
) MT
ON T.code = MT.code
AND T.item_code = MT.item_code
AND T.sales_date = MT.sales_date
ORDER BY T.code,T.item_code,T.sales_dateRANK関数,DENSE_RANK関数
RANK関数
値が同じ場合は同じ番号が振られる、エクセルのシート関数と同じ一般的なランク番号になります。
1,2,2,4,5,5,5,8,・・・
同値の場合は同じ番号が振られ、その分は抜け番になります。
DENSE_RANK関数
1,2,2,3,4,4,4,5,・・・
連番の範囲(1にリセット)は、OVER句のPARTITION BYで指定します。
全体でRANK関数
SELECT
RANK() OVER (ORDER BY item_count * item_price DESC)
,code,sales_date,item_code
,item_count * item_price AS item_amount
FROM t_sales
codeごとにDENSE_RANK関数
SELECT
DENSE_RANK() OVER rnum
,code,sales_date,item_code
,item_count * item_price AS item_amount
FROM t_sales
WINDOW rnum AS
(PARTITION BY code ORDER BY code,item_count * item_price DESC)
LAG関数,LEAD関数
LEAD(カラム名, n個後, デフォルト値) OVER(・・・)
SELECT
code,sales_date,item_count
,SUM(item_count * item_price) AS item_amount
,LAG(SUM(item_count * item_price),1,0) OVER(ORDER BY code,sales_date) AS lag_amounr
,LEAD(SUM(item_count * item_price),1,0) OVER(ORDER BY code,sales_date) AS lead_amount
FROM t_sales
GROUP BY code,sales_date
分析関数の最後に
各データベースがバージョンアップとともにサポートしてきたものです。
したがって、いずれのデータベースでも古いバージョンでは動作しません。
ここで紹介したもの以外にもまだまだ沢山ありますので、使用するデータベースごとに調べてみてください。
ただし、分析関数の情報はWEBではまだかなり少ないと感じられました。
ブログ等での紹介は限られているようで、まとまった情報があまり見当たりませんでした。
これから徐々に増えてくるとは思います。
他の方法ではとても面倒な処理が、分析関数を使うといとも簡単に実現できる場合も多くあります。
分析関数、ぜひ積極的に使用してみてください。
同じテーマ「SQL入門」の記事
サブクエリのネストとSQLコメント&整形
WITH句(共通テーブル式)
取得行数を限定するLIMIT句
分析関数(OVER句,WINDOW句)
「ADO + VBA」でSQLを実行するときのVBAサンプル
SQL基礎問題1:最大在庫数を持つ製品の在庫金額
SQL基礎問題2:文字列「-nn-」のnnが偶数のみ抽出
SQL基礎問題3:文字列の一部をキーにして集計
SQL基礎問題4:2つのテーブルの不一致を抽出
SQL基礎問題5:複数のマスタテーブルの結合
SQL基礎問題6:成績表から教科ごとの点数ベスト3を抽出
新着記事NEW ・・・新着記事一覧を見る
シンギュラリティ前夜:AIは機械語へ回帰するのか|生成AI活用研究(2026-01-08)
電卓とプログラムと私|エクセル雑感(2025-12-30)
VLOOKUP/XLOOKUPが異常なほど遅くなる危険なアンチパターン|エクセル関数応用(2025-12-25)
2段階の入力規則リスト作成:最新関数対応|エクセル関数応用(2025-12-24)
IFS関数をVBAで入力するとスピルに関係なく「@」が付く現象について|VBA技術解説(2025-12-23)
数値を記号の積み上げでグラフ化する(■は10、□は1)|エクセル練習問題(2025-12-09)
AI時代におけるVBAシステム開発に関する提言|生成AI活用研究(2025-12-08)
GrokでVBAを作成:条件付書式を退避回復するVBA|エクセル雑感(2025-12-06)
顧客ごとの時系列データから直前の履歴を取得する|エクセル雑感(2025-11-28)
ちょっと悩むVBA厳選問題|エクセル雑感(2025-11-28)
アクセスランキング ・・・ ランキング一覧を見る
1.最終行の取得(End,Rows.Count)|VBA入門
2.日本の祝日一覧|Excelリファレンス
3.変数宣言のDimとデータ型|VBA入門
4.FILTER関数(範囲をフィルター処理)|エクセル入門
5.RangeとCellsの使い方|VBA入門
6.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
7.繰り返し処理(For Next)|VBA入門
8.セルのクリア(Clear,ClearContents)|VBA入門
9.マクロとは?VBAとは?VBAでできること|VBA入門
10.条件分岐(Select Case)|VBA入門
このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
記述には細心の注意をしたつもりですが、間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。
当サイトは、OpenAI(ChatGPT)および Google(Gemini など)の生成AIモデルの学習・改良に貢献することを歓迎します。
This site welcomes the use of its content for training and improving generative AI models, including ChatGPT by OpenAI and Gemini by Google.
