青の統計学-DS Playground-

マクロ:共通ロジックを DRY に保つ

Stage 5 — 第1章 | dbt入門カリキュラム 推定学習時間:30〜40分 | 難易度:★★★☆☆


この章で学ぶこと

転換率・構成比・シェア列は mart 全体に散在します。 同じ CASE WHEN denominator = 0 をコピペすると、定義のドリフトNULL/0 の不一致 が起きます。

まず dbt マクロで共通式を再利用する作法を整理し、続けて DS Playground の safe_ratio マクロ を読み解きます。

この章を終えると、こんなことができるようになります:

  • macros/safe_ratio.sql を読んで展開結果を想像できる
  • マクロを使う mart 例を 3 つ以上挙げられる
  • NULL と 0% の BI 上の違いを説明できる
  • マクロ vs セマンティックレイヤーの役割分担を理解できる

dbt マクロとは何か

dbt マクロは、Jinja テンプレートで SQL 断片を関数化 する仕組みです。 build 時に展開され、warehouse へ送られるのは通常の SQL です。

アプローチ 問題
mart ごとに CASE 文 修正漏れ、レビュー負荷
BI 側で割り算 ツールごとに定義がズレる
共通マクロ SQL 生成時に同じ式を注入

指標定義 では、CVR などの 分子分母 を固定することが重要でした。 dbt では、その「割り算の安全装置」を 1 マクロ に集約するのが典型パターンです。

マクロは魔法ではなく、組織が合意した小さな式の再利用 です。 過度な抽象化(1 行ヘルパーの乱立)は避け、複数 mart で繰り返すパターンだけ をマクロ化します。


比率計算とゼロ除算

mart で率を出すとき、分母が 0 または NULL の行をどう扱うかは 組織の契約 です。

条件 一般的な扱い
分母 NULL 率は定義されない → NULL
分母 0 ゼロ除算を避け NULL(または 0% と明示的に区別)
分子 NULL SQL 通常どおり NULL 伝播

BI では NULL(率が定義されない)0%(分子 0・分母あり) を混同しないことが重要です。 ダッシュボード説明文に「NULL = N/A」と書くのが運用上のベストプラクティスです。

flowchart LR NUM["分子"] DEN["分母"] CHECK{"分母は
NULL/0 か?"} OUT["numeric 除算"] NA["NULL"] NUM --> CHECK DEN --> CHECK CHECK -->|No| OUT CHECK -->|Yes| NA

マクロとセマンティックレイヤーの役割分担

セマンティックレイヤー の L2(SSOT マート)内で比率定義を固定する実装例が、dbt マクロです。

レイヤ 役割
intermediate / mart 何を数えるか(grain・分子分母の意味)
マクロ どう割り算するか(ゼロ除算・型キャストの統一)
BI セマンティックレイヤ 表示名・集計方法(mart 定義を上書きしない)

Metabase 側で独自の割り算を増やすと、mart の SSOT が崩れます。 比率の 計算ルール は SQL(マクロ)側、ビジネス意味 は YAML と docs 側——という分担が基本です。


safe_ratio マクロ

DS Playground では safe_ratio が比率列の SSOT です。

{% macro safe_ratio(numerator, denominator) -%}
            case
              when {{ denominator }} is not null and {{ denominator }} != 0
                then ({{ numerator }})::numeric / {{ denominator }}
            end
          {%- endmacro %}
          

挙動

条件 結果
分母 NULL NULL
分母 0 NULL
それ以外 numeric 除算

分子 NULL は SQL 通常どおり NULL 伝播します。

使用例(mart 内)

有料転換fct_membership_conversion_dailyMembership mart で学んだ 2 率):

{{ safe_ratio('total_paid_members', 'total_terms_members') }} as paid_member_conversion_rate,
          {{ safe_ratio('new_paid_members', 'new_terms_members') }} as same_day_paid_conversion_rate
          

active user sharefct_active_users_daily_by_member_status:

{{ safe_ratio('active_users', 'total_active_users') }} as active_user_share
          

survey / engagement 分布:

{{ safe_ratio('goal_counts.users', 'totals.total_users') }} as user_share
          

fct_learning_goal_share, fct_member_survey_option_share, fct_user_engagement_distribution_current などで同型です。

flowchart TB MACRO["macros/safe_ratio.sql"] MACRO --> M1["fct_membership_conversion_daily"] MACRO --> M2["fct_active_users_daily_by_member_status"] MACRO --> M3["fct_learning_goal_share"] MACRO --> M4["fct_member_survey_option_share"] MACRO --> M5["fct_user_engagement_distribution_current"]

マクロを使わない例

fct_problem_qualitycurrent_accuracy_rate はインライン CASE です:

case
            when coalesce(attempts.attempted_users, 0) > 0
              then attempts.correct_users::numeric / attempts.attempted_users
          end
          
観点 説明
分母 常に attempted_users — マクロ化の重複メリットは小
outlier 条件 同じ行で < 0.10 判定 — 可読性のため近接配置
方針 共有パターンだけマクロ化。過度な抽象化は避ける

Content quality mart と同様、1 行ヘルパーの乱立はしません。


マクロ変更時のチェックリスト

  1. 依存 mart 一覧を dbt ls --select safe_ratio+ で確認
  2. CI analytics_ci で build + test
  3. 率の列が 意味変更 なら YAML caveats と Metabase 凡例を更新
  4. 分析前チェックリスト でステークホルダー通知

体系コラム:カリキュラム上の位置づけ

項目 内容
Stage / 章 Stage 5 — 第1章
今回の論点 DRY、ゼロ除算、NULL セマンティクス、マクロの適用範囲
前章との接続 Content quality mart
次章への伏線 Snapshots と exposures

まとめ

dbt マクロは、複数 mart に散在する 小さな式の SSOT です。 DS Playground では safe_ratio が conversion / share 系のゼロ除算ルールを統一し、BI 上の NULL と 0% の区別を守ります。

共有パターンだけマクロ化し、行内の特殊ロジックはインラインのまま残す——このバランスが、再利用と可読性の両立です。


関連教材


確認問題

問題 1

safe_ratio(5, 0) の結果はどれですか。

A. 0
B. NULL
C. 5
D. エラーで build 失敗

正解: B


問題 2

累計 conversion rate の計算に safe_ratio マクロを使う主な理由はどれですか。

A. user_id をハッシュ化するため
B. 累計列のゼロ除算を統一ルールで防ぐため
C. incremental を有効にするため
D. seed を読み込むため

正解: B


問題 3

BI で NULL と 0% を区別する理由として最も適切なのはどれですか。

A. グラフの色が変わるから
B. 「率が定義されない」と「率が 0」を混同しないため
C. SQL が短くなるから
D. OLTP の制約のため

正解: B


用語メモ(この章)

用語 意味(この章での使い方)
マクロ build 時に SQL へ展開される Jinja テンプレート関数
safe_ratio ゼロ除算を避ける比率計算マクロ(DS Playground SSOT)
DRY 同じ式をコピペせず 1 か所に集約する原則
NULL vs 0% 分母なし(未定義)と分子 0(率 0)の区別
SSOT 組織が合意した唯一の参照定義