Caution
お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。
LAG / LEAD
ウィンドウ関数の1つで、現在の行から前後のN行の値を参照できる関数です。売上の前日比・前月比の計算など、時系列データの比較によく使われます。
構文
-- LAG: N行前の値を参照します。 LAG(列名 [, N [, デフォルト値]]) OVER ([PARTITION BY グループ列] ORDER BY 並び順列) -- LEAD: N行後の値を参照します。 LEAD(列名 [, N [, デフォルト値]]) OVER ([PARTITION BY グループ列] ORDER BY 並び順列)
構文一覧
| 関数 | 概要 |
|---|---|
| LAG(列, N, デフォルト) | 現在行のN行前の値を返します。Nを省略すると1行前になります。参照先がない場合はデフォルト値(省略時はNULL)を返します。 |
| LEAD(列, N, デフォルト) | 現在行のN行後の値を返します。Nを省略すると1行後になります。参照先がない場合はデフォルト値(省略時はNULL)を返します。 |
サンプルコード
-- 前日の売上と差額を計算します。
SELECT
売上日,
売上金額,
LAG(売上金額, 1, 0) OVER (ORDER BY 売上日) AS 前日売上,
売上金額 - LAG(売上金額, 1, 0) OVER (ORDER BY 売上日) AS 前日比
FROM 日別売上
ORDER BY 売上日;
-- 商品カテゴリ別に前月売上と翌月売上を並べて比較します。
SELECT
売上月,
カテゴリ名,
売上金額,
LAG(売上金額) OVER (PARTITION BY カテゴリ名 ORDER BY 売上月) AS 前月売上,
LEAD(売上金額) OVER (PARTITION BY カテゴリ名 ORDER BY 売上月) AS 翌月売上
FROM 月別カテゴリ売上
ORDER BY カテゴリ名, 売上月;
実行結果
-- 前日比。 売上日 | 売上金額 | 前日売上 | 前日比 ------------+----------+----------+-------- 2024-01-01 | 120000 | 0 | 120000 2024-01-02 | 98000 | 120000 | -22000 2024-01-03 | 145000 | 98000 | 47000 2024-01-04 | 88000 | 145000 | -57000 -- カテゴリ別・月別の前後比較。 売上月 | カテゴリ名 | 売上金額 | 前月売上 | 翌月売上 ---------+------------+----------+----------+--------- 2024-01 | 家電 | 850000 | NULL | 920000 2024-02 | 家電 | 920000 | 850000 | 780000 2024-03 | 家電 | 780000 | 920000 | NULL
データベース別の書き方
『LAG()』『LEAD()』は MySQL(8.0以降)・PostgreSQL・Oracle・SQL Server・SQLite(3.25以降)で共通して使用できます。
-- 前日の売上と差額を計算します(主要データベース共通)。
SELECT
売上日,
売上金額,
LAG(売上金額, 1, 0) OVER (ORDER BY 売上日) AS 前日売上,
売上金額 - LAG(売上金額, 1, 0) OVER (ORDER BY 売上日) AS 前日比
FROM 日別売上
ORDER BY 売上日;
概要
『LAG』と『LEAD』はN行前後の値を返すウィンドウ関数です。第2引数でオフセット(省略時は1)、第3引数で参照先が存在しない場合のデフォルト値を指定できます。デフォルト値を省略すると NULL が返ります。
前日比・前月比の計算は自己結合(SELF JOIN)でも実現できますが、LAG/LEAD の方がコードが簡潔です。PARTITION BY を付けるとグループごとに独立した前後参照になるため、複数の系列を1つのテーブルに持つ場合は必ず指定してください。指定しないとグループをまたいで参照されます。
ウィンドウ関数の基本構文は『OVER / PARTITION BY』を、累計・移動平均は『SUM / AVG(ウィンドウ)』を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。