SQL Interview Prep · レッスン

期間ごとの変化を求める

LAGを使って前月比の成長率や前日との差分を計算します。

レッスン 2/413 ステップ

「期間ごとの変化を求める」はCoddyKit上の無料SQL Interview Prepレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSQL Interview Prep学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 SQL Interview Prepコースには全4レッスンが含まれています。

アナリストなら必ず問われる質問

データアナリスト職の面接では、「前月比の成長率を計算してください」や「前日比の変化はどれくらいですか?」といった質問を想定してください。ほぼ避けては通れません。

基本となるのはLAGです。前の期間の値を取得し、絶対差分または変化率を計算します。このレッスンでは、面接官が評価する期間比較のパターンにLAGを活用します。

LAGによる絶対変化

最も単純な形は、現在の期間と前の期間との差をそのまま求める方法です。LAGで以前の値を取得し、式の中で差し引きます。

順序付けされた最初の行には前の行がないため、変化量はNULLになります。これはバグではなく正しい結果です。比較対象となる前の期間が実際に存在しないためです。

SELECT
  month,
  revenue,
  revenue - LAG(revenue) OVER (ORDER BY month) AS mom_change
FROM monthly_sales
ORDER BY month;

変化率

面接では通常、成長をパーセントで求められます。式は(current - previous) / previousに100を掛けたものです。これをLAGで直接表現します。

演算の順序と括弧に注意してください。括弧の位置を間違えるのは、プレッシャーのかかる場面でよくあるミスです。

SELECT
  month,
  revenue,
  100.0 * (revenue - LAG(revenue) OVER (ORDER BY month))
        / LAG(revenue) OVER (ORDER BY month) AS pct_growth
FROM monthly_sales
ORDER BY month;

整数除算を避ける

多くの候補者が陥る落とし穴があります。revenueが整数の場合、整数除算を行うデータベースでは(110 - 100) / 100の結果が0になります。

浮動小数点リテラルである100.0を掛けるか、先にCASTで小数型に変換して、浮動小数点演算を強制してください。これを先回りして説明できると、細部への注意力を示せます。

SELECT
  month,
  ROUND(
    100.0 * (revenue - LAG(revenue) OVER (ORDER BY month))
          / LAG(revenue) OVER (ORDER BY month), 2
  ) AS pct_growth
FROM monthly_sales;

より明快に:CTEで一度だけ計算する

分子と分母でLAGを2回呼び出すと、記述が重複し、入力ミスも起こりやすくなります。よくあるリファクタリングは、CTEで以前の値を一度だけ計算し、外側のクエリで計算処理を行う方法です。

ホワイトボード面接でも読みやすく、2つのLAG呼び出しの内容が食い違うことも防げます。

WITH t AS (
  SELECT
    month,
    revenue,
    LAG(revenue) OVER (ORDER BY month) AS prev
  FROM monthly_sales
)
SELECT
  month,
  revenue,
  ROUND(100.0 * (revenue - prev) / prev, 2) AS pct_growth
FROM t;

0除算を防ぐ

前の期間の値が0になる可能性がある場合、変化率の式は0で割ることになり、エラーが発生します。NULLIF(prev, 0)を使うと分母がNULLになるため、例外ではなく結果がNULLになります。

このように除算を防御的に扱えると、本番運用を意識できる候補者として面接官の目に留まります。

SELECT
  month,
  revenue,
  100.0 * (revenue - prev) / NULLIF(prev, 0) AS pct_growth
FROM (
  SELECT month, revenue,
         LAG(revenue) OVER (ORDER BY month) AS prev
  FROM monthly_sales
) s;

グループごとの期間比較

実際の質問の多くは範囲が限定されています。たとえば、商品ごとまたは地域ごとの前月比成長率です。PARTITION BYを追加し、各グループの系列をそれぞれ自身とだけ比較します。

各グループの最初の月はNULLにリセットされ、商品間の境界をまたいで比較されることはありません。

SELECT
  product_id,
  month,
  revenue,
  revenue - LAG(revenue) OVER (
    PARTITION BY product_id
    ORDER BY month
  ) AS mom_change
FROM product_sales;

オフセットによる前年比

月単位のデータで各行が1か月分の間隔になっている場合、前年比では12行前の値と比較します。オフセット引数を使えば、LAG(revenue, 12)と直接指定できます。

これは月ごとに1行あり、欠損月がないことを前提としています。月が欠ける可能性がある場合は、代わりに明示的な日付で結合します。この点は、口頭で説明すると評価される細かな注意点です。

SELECT
  month,
  revenue,
  revenue - LAG(revenue, 12) OVER (ORDER BY month) AS yoy_change
FROM monthly_sales
ORDER BY month;

比較前に集計する

生のイベントテーブルは、月ごとにあらかじめ合計されているわけではありません。実際的な解答では、まず期間ごとに1行になるよう集計し、その後、通常はCTEを使って集計結果にLAGを適用します。

集計していない行に対してLAGを使うと、月ごとの合計ではなく個々のトランザクションを比較することになります。これはよくある論理エラーです。

WITH monthly AS (
  SELECT DATE_TRUNC('month', order_date) AS mth,
         SUM(amount) AS revenue
  FROM orders
  GROUP BY 1
)
SELECT mth, revenue,
       revenue - LAG(revenue) OVER (ORDER BY mth) AS mom_change
FROM monthly
ORDER BY mth;

最初のNULLを解釈する

面接官から「最初の行の成長率がNULLなのはなぜですか。それで問題ありませんか」と聞かれることがあります。正しい答えは、前の期間が存在しないため変化は未定義であり、NULLがその状態を正しく表している、というものです。

業務上0が必要な場合は、LAG(revenue, 1, 0)またはCOALESCEを使います。ただし、それが意図する意味と一致する場合に限ってください。

増減方向にラベルを付ける

面接官は、「各月について、増加、減少、横ばいのどれかも示してください」と質問を発展させることがあります。LAGとの比較をCASE式で囲みます。

以前の値と比較すると、数値の差分に加えて、人が読みやすい明確な傾向列を作れます。また、比較対象のない最初の期間についても、NULLまたはデフォルトのラベルを適切に表示できます。

SELECT
  month,
  revenue,
  CASE
    WHEN revenue > LAG(revenue) OVER (ORDER BY month) THEN 'up'
    WHEN revenue < LAG(revenue) OVER (ORDER BY month) THEN 'down'
    ELSE 'flat'
  END AS trend
FROM monthly_sales
ORDER BY month;

確認問題

変化率のクエリでよくあるミスを見つけましょう。

まとめ

期間ごとの変化は、LAGと算術演算の組み合わせです。

  • 絶対変化:value - LAG(value) OVER (ORDER BY period)
  • 変化率:100.0 * (value - prev) / NULLIF(prev, 0)
  • 浮動小数点演算を強制し、0除算を防ぎ、期間ごとに1行になるよう事前集計します。
  • PARTITION BYで範囲を限定し、前年比にはオフセットを使います。

次は、NTILEを使って行をバケットとティアに分けます。

無料で開始

AI チューターと学ぶ SQL — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
30
レッスン
120

よくある質問

「期間ごとの変化を求める」レッスンは無料ですか?

はい。「期間ごとの変化を求める」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、SQL Interview Prepコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 SQL Interview Prepコースには全4レッスンが含まれています。

「期間ごとの変化を求める」で何を学びますか?

LAGを使って前月比の成長率や前日との差分を計算します。 ブラウザで直接実行するハンズオンコードでSQL Interview Prepを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

SQL Interview Prepを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのSQL Interview Prepは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「期間ごとの変化を求める」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このSQL Interview Prepレッスンでコードを書いて実行できますか?

はい。すべてのSQL Interview Prepレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. LAGとLEADで隣接行を参照する
  2. 期間ごとの変化を求める
  3. NTILEで区分に分ける
  4. FIRST_VALUE、LAST_VALUE、フレーム端点
← SQL Interview Prepに戻る