MoM成長率 — LAG() で前月の値を引き寄せ、前月比・前月差を計算する
月次売上やMAUの「前月比成長率(MoM, Month-over-Month)」は経営報告の必須KPIです。これは同じ行に「今月の値」と「先月の値」を並べることで初めて計算できます。LAG() は、ORDER BY で並べた中でN行前の値を現在行へ引き寄せるウィンドウ関数で、まさにこの用途の定番です。
LAG(revenue) OVER (ORDER BY month) -- 1つ前の行の revenue(既定オフセット=1) LAG(revenue, 12) OVER (ORDER BY month) -- 12行前=前年同月(YoY)も同じ文法で LEAD(revenue) OVER (ORDER BY month) -- LEAD は逆に「次の行」を引き寄せる
(今月 − 先月) / 先月。先月が 0 だとゼロ除算エラーになります。NULLIF(prev, 0) で分母が0のとき NULL に化けさせ、エラーを回避するのが実務の定石です。先頭月は先月が存在せず LAG が NULL を返すため、成長率も自然に NULL になります。monthly_revenue から、各月の売上・前月売上・前月差(mom_diff)・前月比成長率(mom_pct, %)を計算してください。出力列は month, revenue, prev_revenue, mom_diff, mom_pct、month 昇順、成長率は小数第2位まで丸めてください。
| month | revenue |
|---|---|
| 2024-01 | 1000 |
| 2024-02 | 1200 |
| 2024-03 | 1100 |
| 2024-04 | 1500 |
| 2024-05 | 1500 |
| 2024-06 | 1800 |
| month | revenue | prev_revenue | mom_diff | mom_pct |
|---|---|---|---|---|
| 2024-01 | 1000 | NULL | NULL | NULL |
| 2024-02 | 1200 | 1000 | 200 | 20.00 |
| 2024-03 | 1100 | 1200 | -100 | -8.33 |
| 2024-04 | 1500 | 1100 | 400 | 36.36 |
| 2024-05 | 1500 | 1500 | 0 | 0.00 |
| 2024-06 | 1800 | 1500 | 300 | 20.00 |
顧客セグメント — NTILE() で支出を四分位に等分割しランク帯を作る
「上位25%の優良顧客」「支出の四分位(クォータイル)でランク帯を切る」——こうした等量分割によるセグメンテーションは NTILE(n) の出番です。NTILE は ORDER BY で並べた行をできるだけ均等な n 個のバケツに分け、各行へバケツ番号(1〜n)を振ります。
NTILE(4) OVER (ORDER BY spend DESC) -- 支出降順で4等分。1=上位25%, 4=下位25% -- 行数が割り切れないとき、余りは「前のバケツ」から1行ずつ多く配られる -- 例: 9行を4分割 → 3,2,2,2(先頭バケツが1行多い)
customer_spend から、支出降順で顧客を4分割(四分位)し、帯ごとに VIP / Gold / Silver / Bronze のラベルを付与してください。出力列は user_id, spend, quartile, segment、spend 降順で返してください。
| user_id | spend |
|---|---|
| U1 | 100 |
| U2 | 250 |
| U3 | 400 |
| U4 | 550 |
| U5 | 700 |
| U6 | 900 |
| U7 | 1200 |
| U8 | 1500 |
| U9 | 1800 |
| user_id | spend | quartile | segment |
|---|---|---|---|
| U9 | 1800 | 1 | VIP |
| U8 | 1500 | 1 | VIP |
| U7 | 1200 | 1 | VIP |
| U6 | 900 | 2 | Gold |
| U5 | 700 | 2 | Gold |
| U4 | 550 | 3 | Silver |
| U3 | 400 | 3 | Silver |
| U2 | 250 | 4 | Bronze |
| U1 | 100 | 4 | Bronze |
ファネル分析 — COUNT(DISTINCT)+FIRST_VALUE/LAG でステップ別CVRを出す
「閲覧 → カート → 購入」と進むユーザーがどこで脱落するか——ファネル分析はコンバージョン改善の出発点です。各ステップの到達ユーザー数を数え、ステップ間の転換率(CVR)を求めます。CVR には2つの定義があり、両方を1クエリで並べると示唆が深まります。
-- ① 全体CVR : 入口(最初のステップ)を分母にした通過率 FIRST_VALUE(users) OVER (ORDER BY step_no) -- 並びの先頭値=入口の人数で固定 -- ② ステップCVR: 直前のステップを分母にした転換率 LAG(users) OVER (ORDER BY step_no) -- 1つ前のステップの人数
CASE step WHEN 'view' THEN 1 ... で並び順を表す step_no を明示的に与えるのがポイント。ファネルは順序が命です。events(行動ログ)から、各ステップの到達ユーザー数(重複排除)と、全体CVR・ステップCVRを求めてください。出力列は step, users, overall_cvr, step_cvr、ファネル順(view→cart→purchase)で返し、CVRは%・小数第2位まで。
| user_id | step |
|---|---|
| U1 | view |
| U1 | cart |
| U1 | purchase |
| U2 | view |
| U2 | cart |
| U3 | view |
| U4 | view |
| U4 | cart |
| U4 | purchase |
| U5 | view |
| U6 | view |
| U6 | cart |
| step | users | overall_cvr | step_cvr |
|---|---|---|---|
| view | 6 | 100.00 | NULL |
| cart | 4 | 66.67 | 66.67 |
| purchase | 2 | 33.33 | 50.00 |
コホート・リテンション — 経過月数で条件付き集計し残存率マトリクスを作る
コホート分析は「いつ獲得したか(登録月)」でユーザーを束ね、その後の経過月ごとの残存率(リテンション)を追う手法です。獲得施策やプロダクト改善の効果を、世代(コホート)横断で比較できます。鍵は2つ——経過月数(month_offset)の算出と、それを列に展開する条件付き集計(ピボット)です。
-- 経過月数 = 活動月 − 登録月(月単位の差) (EXTRACT(YEAR FROM (active_month || '-01')::date) - EXTRACT(YEAR FROM (cohort_month || '-01')::date)) * 12 + (EXTRACT(MONTH FROM (active_month || '-01')::date) - EXTRACT(MONTH FROM (cohort_month || '-01')::date)) -- ピボット:経過月ごとの在籍人数を横に並べる(重複排除) COUNT(DISTINCT user_id) FILTER (WHERE month_offset = 1) -- 1ヶ月後の在籍数
NULLIF(m0, 0) でゼロ除算を防ぎます。チャーン率(基礎編)はこの裏返し(1 − リテンション)です。activity(登録月コホート × 活動月)から、コホート別の初月人数と1ヶ月後・2ヶ月後リテンション率を出してください。出力列は cohort_month, cohort_size, ret_m1, ret_m2、cohort_month 昇順、率は%・小数第1位まで。
| user_id | cohort_month | active_month |
|---|---|---|
| U1 | 2024-01 | 2024-01 |
| U1 | 2024-01 | 2024-02 |
| U1 | 2024-01 | 2024-03 |
| U2 | 2024-01 | 2024-01 |
| U2 | 2024-01 | 2024-02 |
| U3 | 2024-01 | 2024-01 |
| U4 | 2024-02 | 2024-02 |
| U4 | 2024-02 | 2024-03 |
| U4 | 2024-02 | 2024-04 |
| U5 | 2024-02 | 2024-02 |
| U5 | 2024-02 | 2024-03 |
| cohort_month | cohort_size | ret_m1 | ret_m2 |
|---|---|---|---|
| 2024-01 | 3 | 66.7 | 33.3 |
| 2024-02 | 2 | 100.0 | 50.0 |
再帰CTE — 日付スパインを生成し、欠損日を0で埋めた連続時系列を作る
日次の売上やDAUは、活動が無い日にそもそも行が存在しないことがよくあります。このまま折れ線や移動平均(基礎編)にかけると、欠損日が詰められてグラフも計算もズレます。解決策は連続した日付の骨組み(日付スパイン)を自前で生成し、そこへ実績を左結合して欠損日を0で補完することです。骨組み生成の王道が再帰CTEです。
WITH RECURSIVE calendar AS ( SELECT DATE '2023-08-01' AS d -- ① アンカー:起点の1行(非再帰項) UNION ALL -- ② 結果を縦に積み増す SELECT d + 1 FROM calendar -- ③ 再帰項:自分自身を参照し+1日 WHERE d < DATE '2023-08-07' -- ④ 終了条件:終点に達したら停止 )
飛び飛びの daily_sales を、2024-03-01〜03-05 の全5日が必ず並び、活動の無い日は売上0となる連続時系列に整えてください。出力列は event_date, sales、日付昇順。再帰CTEで日付スパインを作り、LEFT JOIN + COALESCE で補完します。
| event_date | sales |
|---|---|
| 2024-03-01 | 100 |
| 2024-03-03 | 150 |
| 2024-03-04 | 80 |
| event_date | sales |
|---|---|
| 2024-03-01 | 100 |
| 2024-03-02 | 0 |
| 2024-03-03 | 150 |
| 2024-03-04 | 80 |
| 2024-03-05 | 0 |