「ウィンドウ関数って何?」
SQLに慣れてきたある日、そんな単語が登場しました。
…でも正直、最初に名前だけ聞いたときは、私こう思いました。
「え、Excelのウインドウ枠固定の仲間…?」
「画面分割とか表示系の話?」 まったく違いました…笑
実はこのウィンドウ関数、“行ごとにデータを比べたり、順番をつけたりできる”という、とっても便利な機能なんです。
「前の人の値と比べて◯◯」とか、「この行の順位は◯位」みたいなことが、SQLだけでサクッとできるなんてすごくないですか?
本記事では、ウィンドウ関数のなかでもよく使われる「RANK・LEAD・LAG」を、初心者の方にもわかりやすく&実践で使える形でご紹介します。
SQLでもう一歩先の分析をしてみたい方、ぜひ肩の力を抜いて読んでみてくださいね!
「ウィンドウ関数」ってなんだろう?まずはざっくり理解
SQLを学んでいると、ある日突然「ウィンドウ関数」という謎の言葉に出会います。
名前の響きだけで「え、何か画面を分割する系の関数…?」と思った方、それは私と同じ初見のリアクションですね。
でも実は、ウィンドウ関数の役割はすごくシンプル。
「データを行ごとに扱いながらも、全体の情報も使って計算する」ことができるんです!
ウィンドウ関数=1行ずつの“窓”から全体をのぞくイメージ
ウィンドウ関数を使うと、SQLが「今この行に注目してるけど、他の行の情報も参照したいな~」と考えられるようになります。
例えば、こんな質問
- 「この商品の売上順位は?」 → RANK() を使えばOK!
- 「この行の次のデータは?」 → LEAD() が教えてくれる!
- 「前回のデータと比較したい!」 → LAG() でできる!
SQLなのに“他の行を見ながら処理できる”なんて、ちょっと賢すぎませんか?
ウィンドウ関数と集計関数の違いは?
ウィンドウ関数を理解するには、「普通の集計関数(SUM, AVG)」と何が違うの?」を押さえておくとスムーズです。
内容 | 集計関数 (SUM(), AVG()) | ウィンドウ関数 (RANK(), LEAD(), LAG()) |
---|---|---|
計算単位 | 全体でまとめて1つの値を出す | 各行ごとに計算するが、他の行の情報も参照する |
出力結果 | 1行に集約(例:売上合計だけ) | 全行に結果を表示(例:各商品の順位を出す) |
具体例 | 「売上合計は◯円」 | 「この商品の売上順位は◯位」 |
集計関数は全体をまとめるイメージ、ウィンドウ関数は各行を見ながら処理するイメージ。
この違いを押さえておくだけで、ウィンドウ関数がグッと理解しやすくなります!
「ウィンドウ関数って難しい?」→いいえ、こう考えればOK!
ウィンドウ関数は、言ってしまえば「今この行にフォーカスしつつ、他の情報も参考にする技術」です。
人間でいうなら、「自分のことを考えつつ、周りの状況も気にする」みたいなものですね!
例えば、RANK関数で売上順位をつける場面を考えてみると…
SELECT product_name, sales,
RANK() OVER(ORDER BY sales DESC) AS 売上順位
FROM products;
このクエリを実行すると、各商品の売上順位がズラッと表示されます。
何かを並べたり、ランキングを作るときに超便利ですね!
まとめ:ウィンドウ関数=「行ごとに、他の行と比較しながらデータを扱う」技術
- SQLのウィンドウ関数は、「行を見ながら他の情報も使う」特別な関数
- 集計関数との違いは、「全体で集約するか、各行に適用するか」
- RANK(), LEAD(), LAG() を使えば、順位や前後関係を簡単に取得できる!
次章では「RANK関数を使ってランキングを作る」実践編へ! 実際に手を動かしてみると、ウィンドウ関数の面白さがもっと感じられますよ。
RANK()関数でランキングを作ってみよう
SQLでデータを扱っていると、たまにこんな疑問がわきませんか?
「この商品の売上順位は?」
「テストの得点、誰がトップ?」
「営業成績をランキングで見たい!」
この「順位をつける」問題をサクッと解決できるのが RANK()関数 です!
RANK()の基本構文
SELECT 列1, 列2,
RANK() OVER(ORDER BY 順序を決める列 DESC) AS 順位
FROM テーブル名;
ポイント
- ORDER BY で「何を基準に順位をつけるか」決める
- DESC にすると「大きい順」、ASC にすると「小さい順」
実践①:売上ランキングを出してみよう!
例えば、以下のような products テーブル があるとします
商品名 | 売上金額 |
---|---|
スマホ | 100万 |
ノートPC | 150万 |
タブレット | 80万 |
「売上順にランキングをつけたい!」ときは、こう書きます
SELECT product_name, sales,
RANK() OVER(ORDER BY sales DESC) AS 売上順位
FROM products;
結果
商品名 | 売上金額 | 売上順位 |
---|---|---|
ノートPC | 150万 | 1位 |
スマホ | 100万 | 2位 |
タブレット | 80万 | 3位 |
これだけで、 「売れた順」 に並べられました! もうExcelの手動ソートとはサヨナラですね。
RANK()とDENSE_RANK()の違いは?
例えば、売上が同じ商品があったらどうなるでしょう?
商品名 | 売上金額 |
---|---|
スマホ | 100万 |
ノートPC | 150万 |
タブレット | 100万 |
このとき、 RANK() を使うとこうなります
SELECT product_name, sales,
RANK() OVER(ORDER BY sales DESC) AS 売上順位
FROM products;
商品名 | 売上金額 | RANK順位 |
---|---|---|
ノートPC | 150万 | 1位 |
スマホ | 100万 | 2位 |
タブレット | 100万 | 2位 |
→ 同じ売上の商品は 「同順位」 になります! でも、次の順位は「4位」になり “番号が飛ぶ” のが特徴。
一方で、 DENSE_RANK() を使うと…
SELECT product_name, sales,
DENSE_RANK() OVER(ORDER BY sales DESC) AS 売上順位
FROM products;
商品名 | 売上金額 | RANK順位 |
---|---|---|
ノートPC | 150万 | 1位 |
スマホ | 100万 | 2位 |
タブレット | 100万 | 2位 |
→ RANK()と同じく 「同順位OK」 だけど、次の順位が「3位」になる! 番号の“飛び”がないのが DENSE_RANK()の特徴 です。
どっちを使う?
- 通常のランキングなら RANK() でOK!
- 「順位が連続してほしい」場面では DENSE_RANK() が便利!
まとめ:SQLで順位をつけるのは意外と簡単!
- RANK()関数 を使えば ランキングが一発で作れる
- DENSE_RANK() は「同順位の次の番号を飛ばさない」特徴あり
- 売上・得点・営業成績など、順位データの分析にめちゃくちゃ役立つ!
次章では、「前後のデータを参照する」 LEAD() / LAG()関数 に入ります!
前回値や次の値を比較するテクニックも、データ分析には欠かせません。
LEAD()/LAG()で前後のデータをのぞいてみよう
「前回の売上と比べて、伸びてる?それとも下がってる?」
「昨日のPVと今日のPV、どっちが多い?」
「この商品の次に売れたのはどれ?」
こんな“時系列の比較”や“データの流れ”を知りたい場面って、よくありますよね。
その悩みを SQLでスマートに解決 できるのが LEAD() と LAG() です!
LEAD() と LAG() の基本構文
LEAD(対象列, n) OVER(ORDER BY 並べる列) -- 「n個後のデータ」を取得
LAG(対象列, n) OVER(ORDER BY 並べる列) -- 「n個前のデータ」を取得
ポイント
- LEAD() → 次の行 のデータを参照する
- LAG() → 前の行 のデータを参照する
- n → 何行分のデータを見るか(省略すると「1個先・前」)
これを使えば、「前回との差」や「次の値との関係」 を楽にチェックできます!
実践①:昨日と今日の売上を比較してみよう!
sales テーブル を見てみましょう
日付 | 商品名 | 売上金額 |
---|---|---|
2024-06-15 | スマホ | 100万 |
2024-06-16 | スマホ | 120万 |
2024-06-17 | スマホ | 90万 |
「昨日の売上と比べてどう?」 を確認したいときは、こう書きます
SELECT 日付, 商品名, 売上金額,
LAG(売上金額, 1) OVER(ORDER BY 日付) AS 昨日の売上
FROM sales;
結果
日付 | 商品名 | 売上金額 | 昨日の売上 |
---|---|---|---|
2024-06-15 | スマホ | 100万 | NULL |
2024-06-16 | スマホ | 120万 | 100万 |
2024-06-17 | スマホ | 90万 | 120万 |
これで「昨日との差」を一目でチェックできます!
つまり、 LAG() を使えば、「前のデータ」 を簡単に参照できるんです!
実践②:次の日の売上は? LEAD() を試してみよう!
逆に、「この日の次の売上がどうなるか?」を知りたいときは LEAD() の出番です
SELECT 日付, 商品名, 売上金額,
LEAD(売上金額, 1) OVER(ORDER BY 日付) AS 次の日の売上
FROM sales;
結果
日付 | 商品名 | 売上金額 | 次の日の売上 |
---|---|---|---|
2024-06-15 | スマホ | 100万 | 120万 |
2024-06-16 | スマホ | 120万 | 90万 |
2024-06-17 | スマホ | 90万 | NULL |
これなら、未来のトレンドもつかみやすい!
LEAD() を使えば、「次に来るデータ」 を手軽に取り出せます。
LEAD() / LAG() を組み合わせて「変化」を見てみよう!
売上の「変化」を知りたいなら、LAG() を使って “昨日との差額” を計算してみましょう
SELECT 日付, 商品名, 売上金額,
LAG(売上金額) OVER(ORDER BY 日付) AS 昨日の売上,
売上金額 - LAG(売上金額) OVER(ORDER BY 日付) AS 売上変化
FROM sales;
結果
日付 | 商品名 | 売上金額 | 昨日の売上 | 売上変化 |
---|---|---|---|---|
2024-06-15 | スマホ | 100万 | NULL | NULL |
2024-06-16 | スマホ | 120万 | 100万 | +20万 |
2024-06-17 | スマホ | 90万 | 120万 | -30万 |
「今日は昨日より売上アップ?ダウン?」 が一目瞭然。
こうやってデータの変動をチェックすれば、トレンドの把握 や 成績管理 に活用できます!
まとめ:前後のデータを見て、流れをつかむ
- LAG() → 「前の行のデータ」 を取得(昨日の売上など)
- LEAD() → 「次の行のデータ」 を取得(次の日の予測など)
- 変化を計算すると 「どれくらい増えた?減った?」 が簡単にわかる!
次章では、 ウィンドウ関数の定番パターンを実務で活用する 方法へ。
累積売上・順位の安定化・前後比較など、さらに実践的なテクニックを掘り下げていきます!
ウィンドウ関数の定番パターンを実務で活用しよう
ここまで RANK(), LEAD(), LAG() の基本を学んできましたね!
しかし、ウィンドウ関数はこれらだけではありません。
「ランキングを作る」「前後比較をする」だけでなく、 「累積集計」や「グループごとの傾向分析」 までこなせる、とても強力な技術なんです。
この章では、 実務でよく使うウィンドウ関数のパターン を掘り下げていきましょう!
累積売上の計算(SUM() OVER)
例えば、ある商品の 累積売上(累積合計) を出したいとします。
日付 | 商品名 | 売上金額 |
---|---|---|
2024-06-01 | スマホ | 10万 |
2024-06-02 | スマホ | 15万 |
2024-06-03 | スマホ | 20万 |
累積売上を出したいとき、通常のSUM()だと「全体の合計値」しか取れませんが、 ウィンドウ関数のSUM()を使えば、日ごとの累積売上を出せます!
SELECT 日付, 商品名, 売上金額,
SUM(売上金額) OVER(ORDER BY 日付) AS 累積売上
FROM sales;
結果
日付 | 商品名 | 売上金額 | 累積売上 |
---|---|---|---|
2024-06-01 | スマホ | 10万 | 10万 |
2024-06-02 | スマホ | 15万 | 25万 |
2024-06-03 | スマホ | 20万 | 45万 |
「この時点でどれくらい売れているか?」が簡単にわかる! 営業成績や、売上達成率のモニタリングにも便利ですね。
グループごとのランキング(PARTITION BY を活用)
例えば「各店舗ごとの売上ランキング」を出したい場面を考えてみましょう。
店舗名 | 商品名 | 売上金額 |
---|---|---|
東京店 | スマホ | 120万 |
東京店 | タブレット | 80万 |
大阪店 | スマホ | 100万 |
大阪店 | タブレット | 95万 |
各店舗ごとに「売上ランキング」をつけるなら、 PARTITION BY 店舗名 を使えばOK!
SELECT 店舗名, 商品名, 売上金額,
RANK() OVER(PARTITION BY 店舗名 ORDER BY 売上金額 DESC) AS 売上順位
FROM sales;
結果
店舗名 | 商品名 | 売上金額 | 売上順位 |
---|---|---|---|
東京店 | スマホ | 120万 | 1位 |
東京店 | タブレット | 80万 | 2位 |
大阪店 | タブレット | 95万 | 1位 |
大阪店 | スマホ | 100万 | 2位 |
「各店舗ごとのランキング」を作れる! 地域ごとの売上戦略を立てる際に、こうしたデータが重宝されます。
ウィンドウ関数の活用で、データ分析の幅が広がる!
- 累積データを計算(SUM() OVER) → 日々の積み重ねをチェック
- グループ別ランキングを作成(PARTITION BY) → 部署ごと、店舗ごとなど集計できる
- 前後比較(LAG(), LEAD()) → 昨日との差、未来の予測に活用
こういったテクニックを組み合わせることで、 「データをただ並べる」から「データに意味を持たせる」へ進化 できます!
次章では、 ウィンドウ関数と集計関数の違い&使い分けのコツ を解説していきます。
もう「SQLで高度な分析ができる自分」に近づいてきましたね!
ウィンドウ関数と集計関数はどう違う?使い分けのコツ
SQLを学んでいると、最初に出てくるのは SUM(), AVG(), COUNT() などの集計関数 ですよね。
データをまとめて「合計」「平均」などを算出するシンプルな関数ですが……
その後に ウィンドウ関数(RANK(), LAG(), LEAD() など) が出てきて、
「どっちを使えばいいの?」「どう違うの?」と混乱することがあるかもしれません。
実は、 集計関数とウィンドウ関数は目的が違う んです。
この章では、 その違いと使い分けのコツ を解説していきます!
違いを一言で説明すると…?
集計関数 ➡ 「データをまとめて、1つの結果を出す」
ウィンドウ関数 ➡ 「各行のデータを見ながら、他の情報も使う」
例えば
商品名 | 売上金額 |
---|---|
スマホ | 100万 |
ノートPC | 150万 |
タブレット | 80万 |
このデータで 売上の「合計」 を出したいなら、集計関数を使います。
SELECT SUM(売上金額) AS 総売上
FROM products;
結果
総売上 |
---|
330万 |
→ データ全体をまとめて、1つの結果を出す のが集計関数!
一方、ウィンドウ関数は「各行の情報を残しながら計算」
同じデータで 「各商品の売上順位」 を出したいなら、ウィンドウ関数が登場。
SELECT 商品名, 売上金額,
RANK() OVER(ORDER BY 売上金額 DESC) AS 売上順位
FROM products;
結果
商品名 | 売上金額 | 売上順位 |
---|---|---|
ノートPC | 150万 | 1位 |
スマホ | 100万 | 2位 |
タブレット | 80万 | 3位 |
→ 各行のデータをそのまま保持しつつ、「順位」をつけるのがウィンドウ関数!
簡単な使い分けルール
目的 | 使う関数 |
---|---|
全体の「合計・平均」を出す | 集計関数 (SUM(), AVG() など) |
データをグループごとにまとめる | 集計関数 (GROUP BY とセット) |
各行に「順位」をつける | ウィンドウ関数 (RANK(), DENSE_RANK() など) |
各行ごとに「前後のデータ」を参照 | ウィンドウ関数 (LEAD(), LAG() など) |
「一つの数値を出すなら集計関数」「各行の情報を残すならウィンドウ関数」 のイメージでOK!
実務での具体的な使い分け例
例えば 「売上レポート」を作る場合、こんな使い分けができます。
- 全体の売上合計 ➡ 集計関数 (SUM())
- カテゴリーごとの平均売上 ➡ 集計関数 (GROUP BY + AVG())
- 各商品の売上順位 ➡ ウィンドウ関数 (RANK())
- 前日との差額を出す ➡ ウィンドウ関数 (LAG())
まとめ:「データをどう見たいか?」で選ぶ!
- 「全体の数値を出したい」なら 集計関数!
- 「各行のデータを保持しながら計算したい」なら ウィンドウ関数!
- 「順位」「前後の値」「累積計算」などが必要なら ウィンドウ関数が最適!
この使い分けを押さえておけば、SQLの分析力が グッと上級者レベル に進化します。
次章では 「さらに高度なウィンドウ関数」 について解説! SQLでできることが、もっと広がっていきますよ。
まとめ&次に学ぶべきウィンドウ関数の世界へ
ここまでで、ウィンドウ関数の基本 RANK(), LEAD(), LAG() について学びましたね。
この記事を読んだことで、あなたは 「SQLで順位をつける」「前後データを参照する」「累積計算をする」 という分析技術を手に入れました。
しかし、ウィンドウ関数の世界は まだまだ広い のです!
この章では、次にステップアップするためのおすすめ機能と、実務で活用するコツをご紹介します。
次に学ぶべきウィンドウ関数の一覧
ウィンドウ関数には、これまで学んだ RANK(), LEAD(), LAG() 以外にも強力な機能がそろっています。
関数名 | できること | 使いどころ |
---|---|---|
ROW_NUMBER() | 各行に 「連番」 を振る | ID付与、ページ分割など |
NTILE(n) | データを 「n等分」 してグループ化 | 四分位数分析など |
FIRST_VALUE() | グループごとの 「最初の値」 を取得 | 各カテゴリの代表値 |
LAST_VALUE() | グループごとの 「最後の値」 を取得 | 期間ごとの最新データ |
例えば、 ROW_NUMBER() を使えば「1, 2, 3…」と連番を振れるので、 ページングやレポート作成に便利 です!
ウィンドウ関数を活用するコツ
- 「このデータ、どう分析したい?」から考える
→ 順位?累積?前後比較?それに合う関数を選ぶ - ORDER BY をしっかり指定する
→ ウィンドウ関数は 並び順が超重要! 「何を基準に計算するか」を明確に - PARTITION BY でグループ分けを適切に設定
→ 「全体なのか、カテゴリごとなのか」を意識すると、より正確なデータが取れる!
まとめ:ウィンドウ関数をマスターすれば、SQL分析がもっと楽しくなる!
- ウィンドウ関数は「各行を見ながら計算する」強力なツール
- RANK(), LEAD(), LAG() を使えば、順位付け&前後比較が簡単!
- もっと深い分析をしたいなら、ROW_NUMBER(), NTILE() などにも挑戦!
今後は「時系列分析」「KPI評価」「高度なランキング」 など、 ウィンドウ関数を活かした実務的なデータ分析にも挑戦できます。
SQLの分析力をもっと伸ばして、データと楽しく会話できるスキルを磨いていきましょう!

ウィンドウ関数という、ちょっととっつきにくい名前の技術も、 実際に試してみると 「思ったより使いやすいかも!」 と思えたのではないでしょうか?
SQLは、ただのデータ抽出ツールではなく、「数字に意味を持たせる魔法」 のようなものです。 今回学んだ RANK(), LEAD(), LAG() を活用すれば、 データがただの数字ではなく 「ストーリーを語る存在」 に変わります。
次のステップへ進む準備は、もうできています! この知識を使って、ぜひ 自分のデータで実験しながらスキルを伸ばしてみてくださいね。
コメント