ふくふくHukuhuku Inc.
EP.03dbt 12分公開: 2026-05-10

プロジェクト構造と最初の dbt run:staging → marts のレイヤを組む

dbt の標準プロジェクトレイアウト (staging / intermediate / marts) と命名規則。生データ → 整形 → 集計 の3層を実例で組み、初回 `dbt run` までを通す。

#dbt#プロジェクト構造#staging#marts
シェア

の力は「model のレイヤ分け」から始まります。生データをそのまま分析クエリに使うとカオスになるので、staging → intermediate → marts の 3 層を意識的に組むのが標準パターン。dbt Labs 自身が推奨する best practice guide にも明記されています。

3 層レイヤモデル

レイヤ目的命名materialization
source外部データソースの宣言( は書かない、`schema.yml` のみ)ソース名そのまま
staging1ソース1モデル、型変換とリネームだけ`stg_<source>__<table>.sql`view (ストレージ節約)
intermediate複数 stg を JOIN して中間テーブル`int_<concept>__<verb>.sql`ephemeral or view
martsビジネス指標の正本テーブル`fct_<entity>.sql` / `dim_<entity>.sql`table or incremental
なぜレイヤ分けが必要か

staging で型/命名を揃える → どの marts もここから ref() するので、上流の変更は staging だけ直せばよい。intermediate で重い JOIN を 1 度だけ → marts が読みやすくなる。marts は最終的な分析テーブル で、 ツールはここだけ参照。

ディレクトリ実例

models/ の中身
Text
models/├── staging/│   ├── stripe/│   │   ├── _stripe__sources.yml      # source 宣言│   │   ├── _stripe__models.yml       # stg model 定義 + tests│   │   ├── stg_stripe__charges.sql│   │   ├── stg_stripe__customers.sql│   │   └── stg_stripe__refunds.sql│   └── salesforce/│       └── ...├── intermediate/│   └── int_customer_revenue__monthly.sql└── marts/    ├── core/    │   ├── _core__models.yml    │   ├── dim_customers.sql    │   ├── fct_orders.sql    │   └── fct_revenue_daily.sql    └── finance/        └── fct_invoices.sql

Step 1: source の宣言

models/staging/stripe/_stripe__sources.yml
YAML
version: 2
sources:  - name: stripe                    # source name (ref で 'stripe' と参照)    database: raw                   # 物理 DB (BQ なら project)    schema: stripe                  # 物理 schema (BQ なら dataset)    description: "Stripe からの ELT 取込済み生データ"    freshness:                      # 鮮度監視 (dbt source freshness で確認)      warn_after: { count: 12, period: hour }      error_after: { count: 24, period: hour }    loaded_at_field: _loaded_at     # 鮮度判定に使うカラム
    tables:      - name: charges        description: "Stripe charge イベント"        columns:          - name: id            tests:              - unique              - not_null          - name: amount            description: "金額 (最小通貨単位、JPY なら円)"
      - name: customers        description: "Stripe Customer オブジェクト"

Step 2: staging モデル

models/staging/stripe/stg_stripe__charges.sql
SQL
{{ config(materialized='view') }}
WITH source AS (  SELECT * FROM {{ source('stripe', 'charges') }}),
renamed AS (  SELECT    id              AS charge_id,    customer_id,    amount,    currency,    status,    created         AS charged_at,    refunded,    _loaded_at  FROM source  WHERE status = 'succeeded'   -- staging で軽いフィルタは OK)
SELECT * FROM renamed
staging のお作法

(1) 1 ファイル = 1 ソーステーブル。(2) `source()` を使う ── source 経由でないと dbt が依存を追えない。(3) rename と型変換だけ ── ビジネスロジックは marts で。(4) ほぼ view materialization で OK ── 直下のテーブルは軽量。

Step 3: marts モデル

models/marts/core/fct_revenue_daily.sql
SQL
{{ config(materialized='table') }}
WITH charges AS (  SELECT * FROM {{ ref('stg_stripe__charges') }}),
daily AS (  SELECT    DATE(charged_at) AS date,    currency,    COUNT(DISTINCT customer_id) AS unique_customers,    COUNT(*) AS charge_count,    SUM(amount) AS gross_revenue,    SUM(CASE WHEN refunded THEN amount ELSE 0 END) AS refund_amount,    SUM(amount) - SUM(CASE WHEN refunded THEN amount ELSE 0 END) AS net_revenue  FROM charges  GROUP BY 1, 2)
SELECT * FROM daily

Step 4: 実行

ビルド+テスト
Bash
# 全モデル実行dbt run
# 特定モデルだけdbt run --select fct_revenue_daily
# モデルとその依存元すべて (上流)dbt run --select +fct_revenue_daily
# モデルとその依存先すべて (下流)dbt run --select fct_revenue_daily+
# 親と子両方dbt run --select +fct_revenue_daily+
# テストdbt test --select fct_revenue_daily

命名規則:dbt Labs 推奨

プレフィックス意味
`stg_<source>__<table>`staging (1ソース1モデル)`stg_stripe__charges`
`int_<concept>__<verb>`intermediate (動詞含む)`int_orders__pivoted`
`dim_<entity>`dimension (主体)`dim_customers`
`fct_<entity>`fact (イベント・トランザクション)`fct_orders`
`agg_<grain>`事前集計(任意)`agg_revenue_daily`

次の話

EP.04 では `ref()` と `source()` の挙動を深掘りし、依存グラフがどう作られるかを扱います。

シェア

この記事の感想を教えてください

あなたの 1 クリックで、本当にこの記事は更新されます。「もっと詳しく」「続編希望」が一定数集まった記事は、 ふくふくが 実際に内容を拡充したり続編記事を公開 します。 送信したリアクションはお使いのブラウザに記録され、再カウントされません。

シリーズの外も探す:

まずは、現状を聞かせてください。

要件が固まっていなくて大丈夫です。現状診断と方針提案までを無料でお手伝いします。

無料相談フォームへ hello [at] hukuhuku [dot] co [dot] jp