dbt

dbt generic tests の基本: unique / not_null / accepted_values / relationships を正しく使い分ける

2026-04-19
NicheeLab編集部

dbt の generic tests は、YAML で宣言的にデータ品質を担保できる最初の一歩です。本稿では、最も頻出の4種 unique / not_null / accepted_values / relationships を中心に、挙動と使い分けを実務目線で解説します。

試験対策としては、各テストのパラメータ、NULL の扱い、参照整合性の定義方法、where フィルタや severity などの設定が問われがちです。公式ドキュメントの安定機能に基づいて、再現性のある記述のみを扱います。

generic tests の全体像と YAML 基本形

dbt の generic tests は、モデル(テーブル/ビュー)やその列に対して SQL マクロで生成される検証クエリです。schema.yml(任意名の YAML)にテストを宣言し、dbt test で実行すると、失敗行が返れば失敗、返らなければ成功と判定されます。

代表的な4種は、欠損禁止(not_null)、一意性(unique)、受理値の限定(accepted_values)、参照整合性(relationships)です。where で対象行を絞り、severity で失敗の扱い(error/warn)を制御できます。

  • テストはモデルが実在するリレーション(table/view)に対して実行される点に注意(ephemeral は不可)
  • 多くのテストは where パラメータで行フィルタ可能
  • dbt test -s でテスト選択、-m はモデル選択(バージョンにより -s 推奨)
  • severity: error(既定)/ warn。warn は失敗してもジョブは継続
  • 必要に応じて store_failures で失敗行を永続化(アダプタとバージョンの制約に留意)
テスト主なユースケース失敗が示すこと実務上の注意
not_null必須キーや必須属性の欠損禁止NULL が存在するNULL の意味設計。派生列の NULL は集計ロジックで救済するか検討
unique自然キー/サロゲートキーの一意性重複値、または NULL を含むdbt の unique は NULL も失敗に含む。明示的に not_null と併用すると原因特定が容易
accepted_values状態コード・区分値のホワイトリストリスト外の値、または NULL(許容しない場合)数値や boolean は quote: false。NULL を許可するなら values に null を含める
relationships外部キー整合性(事実→次元)参照先に存在しないキーがある結合キーの型/トリム/大文字小文字。大型事実表ではコストに注意し where でスコープ

テスト定義の流れ(概念)

YAML (schema.yml)generic test macroSQL (fail rows)rendersdbt testsuccess (no rows) / failure (>=1 row)YAML から macro が SQL を描画し、dbt test で 0 行なら成功・1 行以上で失敗

最小の schema.yml 例(4種まとめ)

version: 2
models:
  - name: dim_customers
    columns:
      - name: customer_id
        tests:
          - not_null
          - unique
      - name: status
        tests:
          - accepted_values:
              values: ['active', 'inactive']
              quote: true

  - name: fct_orders
    columns:
      - name: customer_id
        tests:
          - relationships:
              to: ref('dim_customers')
              field: customer_id
          - not_null

not_null の挙動と設計ポイント

not_null は対象列に NULL が存在しないことを検証します。主キー、外部キー、運用上必須な属性に付けるのが基本です。

派生列(例: 正規化や集計で作ったフラグ)の NULL は「未判定」を意味する場合があり、無条件に not_null を付けると運用で詰まることがあります。NULL を許容し、ダッシュボード側で既定値補完する方が安全な場面もあります。

  • 大量行での実行コストは低め(単純な is null スキャン)
  • where で有効期間や is_active = true に限定すると誤検知を避けやすい
  • 実テーブルに NOT NULL 制約がない DWH でも、dbt 側でソフト検証できる
  • 必須キーは not_null と unique をセットで付けるのが試験でも実務でも定番

not_null に where を付ける例

version: 2
models:
  - name: dim_products
    columns:
      - name: product_sku
        tests:
          - not_null:
              where: "is_active = true"

unique は NULL も検知する点に注意

dbt の unique は、重複値に加えて NULL も失敗として扱います(実装上、NULL 行抽出と重複抽出を合成したクエリを生成)。そのため、厳密には unique 単体で not_null を内包します。

ただし、失敗原因の特定を容易にするため、主キー列には not_null と unique を両方記述するのがベストプラクティスです。複合一意性が必要な場合は、サロゲートキーを生成するか、カスタムテスト(あるいは実績あるパッケージのマクロ)を検討します。

  • 主キー: not_null + unique の二段構えで原因切り分け
  • 複合一意はハッシュキー生成(例: sha1(concat_ws))が保守的で安定
  • 重複が多い場合は store_failures で原因行を永続化すると解析しやすい
  • where でスコープを限定(例: 有効期間中のキーのみ)

unique と not_null の併用(主キー想定)

version: 2
models:
  - name: dim_dates
    columns:
      - name: date_key
        tests:
          - not_null
          - unique

accepted_values のコツ(NULL 許容とクオート)

accepted_values は、列の値が事前に許可した集合に含まれるかを検証します。業務コード、状態、フラグ列に有効です。数値・真偽値は quote: false、文字列は quote: true が分かりやすい指定です。

NULL を許容したい場合は、YAML の values に null を含めます(クオートしない null)。大小文字の扱いはデータベースの照合順序に依存するため、必要に応じて列側を正規化してからテストすると安定します。

  • values はホワイトリスト。漏れがあると即失敗
  • 数値・boolean のときは quote: false を明示
  • NULL 許容は values: [.., null] と記述(null は未クオート)
  • where で廃止コードを除外するなどの条件付けが可能

accepted_values の例(NULL 許容、数値型)

version: 2
models:
  - name: dim_status
    columns:
      - name: status
        tests:
          - accepted_values:
              values: ['active', 'inactive', null]
              quote: true
      - name: importance_level
        tests:
          - accepted_values:
              values: [1, 2, 3]
              quote: false
              where: "is_deprecated = false"

relationships で参照整合性を担保する

relationships は、事実テーブルの外部キーが次元テーブルの主キーに存在することを検証します。to で参照先モデル、field で参照先の列を指定します。定義場所が columns セクションなら column_name は暗黙に対象列になります。

巨大な事実表ではコストが高くなりやすいので、where で直近 N 期間に絞るなどの運用が現実的です。キー型の不一致、前後空白、大小文字違いは定番の失敗要因です。

  • 外部キー列は not_null とセットで検証すると漏れを減らせる
  • 参照先のユニーク性(unique)も別途テストしておく
  • 型・トリム・正規化をモデリング段階で統一
  • 一括ロード前後で where による段階的検証が有効

事実テーブルと次元テーブルの参照関係

relationships: to=dim_customers, field=customer_iddim_customerscustomer_id (PK)fct_orderscustomer_id (FK)relationships テストで fct_orders.customer_id が dim_customers.customer_id を参照

relationships の YAML 例(列定義内)

version: 2
models:
  - name: fct_orders
    columns:
      - name: customer_id
        tests:
          - not_null
          - relationships:
              to: ref('dim_customers')
              field: customer_id
              where: "order_date >= dateadd('day', -30, current_date)"

運用ベストプラクティスと試験対策の要点

運用では、スモールスタート(主要キーと主要ディメンションから)でテストを追加し、失敗時の対応手順(連絡先、ロールバック可否、許容度)を runbook 化しておくと安定します。CI では dbt test を PR 毎に実行し、severity=warn を段階的に error に引き上げる方式が安全です。

試験では、各テストの必須パラメータ、NULL の扱い、where・severity・quote の意味、relationships の参照指定(to と field)などが頻出です。unique が NULL も失敗として検知する点はよく問われます。

  • dbt test -s test_type:unique や path 指定でピンポイント実行
  • severity: warn はジョブを落とさずに可視化できる(段階導入に有効)
  • store_failures: true で失敗行を別スキーマに永続化して調査を容易化(アダプタ依存)
  • エラーメッセージはテストごとに特徴があるため、分割定義で原因特定をしやすくする

選択実行と重大度の使い分け(コマンド例)

# 直近で変更のあったモデル配下のテストのみ
# (実環境のバージョン・アダプタに応じてセレクタは調整)
dbt test -s state:modified+ type:generic

# unique テストだけを実行
dbt test -s test_type:unique

# 一部テストを警告扱いに(YAML 側)
version: 2
models:
  - name: fct_orders
    tests:
      - dbt_utils.expression_is_true:
          expression: "total_amount >= 0"
          config:
            severity: warn

問題で確認

Analytics Engineer

問題 1

fct_orders.status は 'pending' または 'completed' のほかに NULL も許容したい。最も適切な accepted_values の定義はどれか?

  1. tests: [accepted_values: {values: ['pending', 'completed', null], quote: true}]
  2. tests: [accepted_values: {values: ['pending', 'completed', 'null'], quote: true}]
  3. tests: [accepted_values: {values: [pending, completed], quote: false}]
  4. tests: [accepted_values: {values: ['pending', 'completed'], allow_nulls: true}]

正解: A

dbt の accepted_values で NULL を許容するには、values に YAML の null を未クオートで含めます。B は文字列 'null' であり NULL ではありません。C は pending/completed を未クオートにしているため文字列として一致しません。D の allow_nulls は組み込みパラメータではありません。

よくある質問

unique と not_null は両方必要ですか?

dbt の unique は NULL も失敗として検知しますが、原因の切り分けとメッセージの明確化のため、主キー列では not_null と unique を併用するのが実務・試験ともに推奨です。

relationships で複合キー(2列以上)を検証できますか?

組み込み relationships は単一列前提です。複合キーは、サロゲートキーをモデル内で生成して relationships を当てるか、カスタムテストを作成して検証する方法が堅実です。

accepted_values で大文字小文字の違いはどう扱われますか?

比較の挙動はデータベースの照合に依存します。確実性が必要なら、モデル側で lower() などで正規化し、accepted_values でも小文字に統一して検証してください。

この記事で学んだ内容を問題で確認しましょう

16,000問以上の問題で実力チェック

無料で問題を解いてみる
この記事の著者

NicheeLab編集部

データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。


関連記事
dbt

dbt Model の基礎: SQL で定義する変換の最小単位

Analytics Engineer 向けに、dbt Model の定義、マテリアライゼーション、依存関係、インクリメン...

dbt

dbt Analytics Engineer 試験ガイド: 出題範囲・配点・申込の実務視点

dbt Analytics Engineer 認定の出題範囲、配点の考え方、申込から受験までの流れを、公式ドキュメントの...

dbt

dbt Cloud と dbt Core の違いと選び方:Analytics Engineer 試験に効く要点

dbt Cloud と dbt Core の機能差を、実務と資格対策の両面から整理。スケジューリング、IDE、RBAC、...

dbt

dbt プロジェクト構造ガイド: models / seeds / macros の実務レイアウト

Analytics Engineer 向けに、dbt プロジェクトのディレクトリ構造と命名規約、dbt_project....

dbt

dbt_project.yml の読み方:主要設定と命名を最短で掴む

dbt_project.yml の必須キー、命名解決(database.schema.identifier)、設定優先度...

dbtの記事一覧 (101件)
© 2026 NicheeLab All rights reserved.