青の統計学-DS Playground-

seeds:参照マスタを repo で持つ

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


この章で学ぶこと

dbt の seeds は、リポジトリ内の CSV など 静的マスタ をデータウェアハウスに load する機能です。 dbt seed で warehouse 上のテーブルになり、他モデルから ref('seed_name') で参照できます。

source が アプリ DB の動的データ なのに対し、seed は Git 管理の参照データ です。 「warehouse に載せたいが、アプリ DB には存在しないマスタ」——カタログ、為替レートのスナップショット、組織コード表など——を repo 側で正本管理するパターンです。

DS Playground では practice_problem_catalog seed が、練習問題 コンテンツの正本(分母) として fct_problem_quality などの marts を支えます。 まず seed の役割と設計判断を整理し、続けて DS Playground の practice_problem_catalog を読み解きます。

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

  • practice_problem_catalog列意味と grain を説明できる
  • 正答率を「回答行だけ」ではなく カタログ対比 で考えられる
  • seed と Supabase problem_attempts役割分担 を説明できる
  • seed 関連 singular test が 分母を守る 理由を理解できる

なぜ seed が必要か

分析で「割合」を語るとき、分母(全体集合) が不明だと指標は意味を失います。 ユーザー行動表だけを見ると、触られた問題だけ が見え、未出題・未回答の問題は分母から漏れます。

データ源 持っているもの 持っていないもの
Supabase problem_attempts ユーザーが 実際に触った 問題の最新状態 未出題・未回答問題
practice/ コンテンツ(Git) 公開問題の 完全一覧 ユーザー行動
seed practice_problem_catalog 上記 JSON から生成した 分析用スナップショット リアルタイム更新(再生成が必要)

コンテンツ品質の問い「カテゴリ X の問題のうち、正答率が低いのはどれか」には 分母(全問題) が必要です。 回答のあった問題だけで割ると、人気問題だけが見える バイアスがかかります。

データマネジメント SSOT の考え方で、コンテンツ定義の正本は Git 側行動データは Supabase 側 と分かれています。 seed は、その Git 正本を分析層へ運ぶ橋 です。

flowchart LR GIT["practice/**/problems.json
コンテンツ SSOT"] SEED["practice_problem_catalog
seed CSV"] WH["warehouse テーブル"] MART["fct_problem_quality"] GIT -->|"生成・同期"| SEED SEED -->|"dbt seed"| WH WH --> MART

seed と source の違い

Stage 1 で学んだ source() との対比です。

source seed
正本 Supabase アプリ DB Git CSV
更新 アプリ運用 コンテンツ PR + 再生成
典型 ユーザー行動 問題マスタ
宣言 _supabase__sources.yml _seeds.yml
参照 source('supabase', 'table') ref('seed_name')

source は 外部システムの鏡、seed は repo 内の参照データ——役割が異なります。 混同しやすいのは「seed も warehouse に載るから source と同じでは?」という点ですが、正本の所在更新トリガー が違います。


practice_problem_catalog

seed ファイルの中身

seeds/practice_problem_catalog.csv の先頭:

category_slug,section_slug,problem_id,problem_title,problem_level,problem_type,category_name
          g-certification,ai-history-and-concepts,ai-history-and-concepts-001,人工知能の定義の捉え方,1,multiple_choice,AIの歴史と概念
          g-certification,ai-history-and-concepts,ai-history-and-concepts-002,AI効果,1,multiple_choice,AIの歴史と概念
          
意味
category_slug 練習カテゴリ(URL スラッグ)
section_slug セクション
problem_id セクション内問題 ID
problem_title 表示タイトル(mart のラベル)
problem_level 著者定義難易度
problem_type 問題形式(例: multiple_choice)
category_name 人間可読カテゴリ名

grain: category_slug + section_slug + problem_id で 1 問題。

seeds YAML — 列契約

第3章 と同様、seed にも schema test を付けられます。

# seeds/_seeds.yml(抜粋)
          seeds:
            - name: practice_problem_catalog
              description: >
                Static practice problem catalog generated from dsplayground/practice/**/problems.json.
                Used as the denominator for content quality and coverage metrics.
              columns:
                - name: category_slug
                  data_tests:
                    - not_null
                - name: section_slug
                  data_tests:
                    - not_null
                - name: problem_id
                  data_tests:
                    - not_null
                - name: problem_level
                  description: "Author-defined difficulty level from the problem JSON."
          
ポイント 説明
description 生成元パスを明示(コンテンツ repo との接続
not_null 結合キーの欠損を seed 段階で禁止
singular と併用 grain 一意は assert_practice_problem_catalog_unique

marts での分母としての JOIN

fct_problem_quality の考え方(概念 SQL):

-- 概念: カタログ LEFT JOIN 最新回答状態
          select
            cat.category_slug,
            cat.section_slug,
            cat.problem_id,
            cat.problem_title,
            cat.problem_level,
            pa.attempt_state,
            pa.attempted_at
          from {{ ref('practice_problem_catalog') }} as cat
          left join {{ ref('stg_supabase__problem_attempts') }} as pa
            on cat.category_slug = pa.category_slug
           and cat.section_slug = pa.section_slug
           and cat.problem_id = pa.problem_id
          

分母側(seed)を LEFT の左 に置くのがポイントです。 全公開問題を保持し、回答の有無・正誤を 任意の属性 として付与します。

flowchart LR SEED[practice_problem_catalog
seed・分母] STG[stg_supabase__problem_attempts
最新回答] MART[fct_problem_quality] T1[assert_practice_problem_catalog_unique] T2[assert_problem_attempts_catalog_covered] SEED --> MART STG --> MART SEED --> T1 SEED --> T2 STG --> T2
出力解釈 意味
JOIN 成功 + correct その問題に最新正解状態あり
JOIN 成功 + incorrect 最新状態が不正解
LEFT JOIN で NULL 未回答 / 未保存(分母には残る)

カテゴリ集約は fct_problem_category_quality が同 seed を分母に使います。 データマート設計 で学んだ「grain を先に決める」が、seed JOIN でもそのまま効きます。


更新運用 — コンテンツ変更と seed

seed は 自動でアプリと同期しない 点に注意します。 コンテンツを変えたら、seed 再生成 → dbt seed / dbt build が必要です。

イベント 必要アクション
新問題追加 problems.json 更新 → seed 再生成 → dbt seed/build
slug リネーム seed + singular 被覆テストが CI で検知
問題削除 seed から消え、attempts に残れば被覆テストが失敗しうる
dsplayground/practice/**/problems.json
                  │(生成スクリプト・手動同期)
                  ▼
          seeds/practice_problem_catalog.csv
                  │ dbt seed / build
                  ▼
          warehouse 上の practice_problem_catalog テーブル
          

パイプライン全体を見ると、コンテンツ(Git)→ seed(repo)→ warehouse → mart(BI) という流れが一本つながります。 seed が古いままだと、mart は 存在しない問題を分母に含めたり、新問題を見落としたり します。


テストによる分母保護

第4章 の singular test が seed を含む横断断言として機能します。

テスト 守るもの
assert_practice_problem_catalog_unique seed 側 grain 重複 → 分母膨張防止
assert_problem_attempts_catalog_covered attempts 側が未知 problem を参照しない
seed 列 not_null 結合キー欠損防止

重複が 1 件あると、同じ問題が 2 回カウント され、カテゴリ品質ランキングが歪みます。 schema test(seed 列の not_null)と singular test(grain 一意・被覆)が 分母の正しさ を二重に守ります。


Stage 2 の位置づけ

Stage 2 では、staging から seed まで Transform の前半 を通しました。

flowchart LR STG["第1–2章
staging・派生列"] TEST["第3–4章
schema / singular tests"] SEED["第5章
seeds"] NEXT["Stage 3 以降
intermediate / marts"] STG --> TEST --> SEED --> NEXT
  • staging … ソースを薄く整える
  • 派生列 … 日付・正規化ルールを明示
  • schema / singular tests … 契約を CI で固定
  • seeds … repo 正本を warehouse へ

この土台の上に、intermediate で KPI 定義を固定し、marts で BI 向けに畳む——という流れが Stage 3 以降です。


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

項目 内容
Stage / 章 Stage 2 — 第5章(Stage 2 完結章)
今回の論点 分母 を warehouse 内に持ち込む設計
前章との接続 singular tests
次章への伏線 intermediate / marts トラック — fct_problem_quality 詳読

まとめ

seed は「小さなマスタ CSV」ではなく、コンテンツ SSOT を分析層へ運ぶ橋 です。 practice_problem_catalog があるから、DS Playground は「触られた問題だけ」ではなく 公開問題全体に対する品質 を語れます。

項目 practice_problem_catalog
役割 練習問題の静的カタログ(分母)
grain category + section + problem_id
生成元 practice/**/problems.json
品質 not_null + unique singular
活用 fct_problem_quality / category_quality

関連教材


確認問題

問題 1

dbt の seed の 主な用途 として最も適切なのはどれですか。

A. OLTP テーブルのリアルタイム同期
B. リポジトリ内 CSV など 静的参照マスタ を warehouse に load する
C. BI ツールのログイン認証
D. 外部 API からの Extract

正解: B


問題 2

割合指標の分母を seed マスタから LEFT JOIN で作る 最も重要な理由 はどれですか。

A. CSV の方が SQL より速い
B. 行動データに現れない ID も分母に含め、母集団全体に対する率を計算できる
C. seed は view にできない
D. source() では JOIN できない

正解: B


問題 3

seed の grain に対する GROUP BY ... HAVING count(*) > 1 型 singular test が検知する問題として 最も近い のはどれですか。

A. 同一キーが seed 内で重複し、分母が水増しされる
B. ユーザーが退会した
C. 数値列が 101 を超えた
D. enum 列に NULL がある

正解: A


用語メモ(この章)

用語 意味(この章での使い方)
seed リポジトリ CSV を load する dbt 機能
分母 割合計算の全体集合(全公開問題)
catalog 問題 ID・タイトル等の一覧
LEFT JOIN 分母全件 + 任意の回答状態
被覆 attempts が catalog を参照できているか