dbt

dbt builtins: this の正しい使い方と動的参照の実務パターン

2026-04-19
NicheeLab編集部

this は「いまコンパイル・実行しているノード(モデル/スナップショット/テスト/フックなど)」を表す Relation を返す dbt の組み込み変数です。

本稿では this の仕組み、ref/source との違い、インクリメンタルでの活用、テストや run-operation での注意点を、試験で狙われやすいポイントに沿ってまとめます。

基礎: this は「現在ノードの Relation」

this は Jinja コンテキストで利用できる組み込み変数で、現在のノードを指すアダプタ依存の Relation オブジェクトを返します。レンダリング時には database.schema.identifier(アダプタが適切にクォート)として展開されます。

this.database / this.schema / this.identifier の各属性にアクセスできます。モデルやスナップショット、テスト、フックで利用可能ですが、ephemeral モデル内での利用は非推奨(物理オブジェクトを持たないため意味が曖昧)です。

  • 可用範囲: モデル、スナップショット、テスト、シード/モデルの pre/post-hook など
  • 返却型: アダプタ固有の Relation(BigQuery なら project.dataset.table、Snowflake なら database.schema.identifier)
  • 属性: database / schema / identifier(環境により database が省略されることあり)
  • 主用途: MERGE/DELETE/GRANT の対象指定、フックやテストでの自己参照
構文目的レンダリング結果の例
this現在ノードの Relation を指すanalytics.core.orders
ref('model_name')依存モデルを解決し DAG を形成analytics.staging.stg_customers
source('src', 'table')外部ソーステーブルを参照raw.sales.customers
target実行ターゲットのメタ(profile/schema など)dev(Relation ではない)

Jinja のレンダリングと this の展開

model.sql (Jinja)select * from {{ this }}dbt compiler依存解決(ref等) / Relation 展開adapter 実行層"db.schema.table"model.sql (Jinja) → dbt compiler → adapter 実行層

最小例: this の属性を参照する

-- models/demo_this.sql
-- 実行時に現在モデルの各構成要素を確認
select
  '{{ this.database }}' as db,
  '{{ this.schema }}'   as sch,
  '{{ this.identifier }}' as id

実務: インクリメンタルでの MERGE/DELETE に this を使う

incremental モデルでは、既存テーブル(ターゲット)と新規ステージングの突合が必要です。this は常に「自モデルの最終的な Relation」を指すため、MERGE/DELETE/INSERT の対象として安全に利用できます。

BigQuery/Snowflake/Databricks など主要アダプタは {{ this }} のクォートと完全修飾を適切に処理します。SQL 方言の差分は WHEN 句や IDENTIFIER クォートに現れますが、this 自体の役割は共通です。

  • MERGE のターゲットに {{ this }} を置くと、環境差異(database/schema 名)の吸収が容易
  • is_incremental() と組み合わせて完全リロード時は SELECT、増分時は MERGE に分岐
  • on_schema_change 設定で列追加の同期も考慮(アダプタ対応範囲に依存)

増分モデルでの定番 MERGE パターン

-- models/fct_orders.sql
{{ config(materialized='incremental', unique_key='order_id', on_schema_change='sync_all_columns') }}

with staged as (
  select * from {{ ref('stg_orders') }}
)

{% if is_incremental() %}
merge into {{ this }} as t
using staged as s
on t.order_id = s.order_id
when matched then update set
  updated_at = s.updated_at,
  total_amount = s.total_amount
when not matched then insert (order_id, updated_at, total_amount)
values (s.order_id, s.updated_at, s.total_amount)
{% else %}
select * from staged
{% endif %}

テスト: this は「テストノード」、model は「被検モデル」を指す

汎用テスト(generic test)のコンテキストでは、しばしば混同が起きます。this はテスト自体(dbt が生成する一時的なテスト関係)を指し、model は被検モデル(ref で解決された Relation)を指します。

列テストを自作する場合、データを読む対象は model、出力(集計結果)の最終書き出し先は this という分担を意識すると混乱を避けられます。

  • 被検データの参照: {{ model }} を使う
  • テスト結果の書き出し先: this(通常は dbt が管理)
  • this を誤ってデータ入力に使うと、意図しない空集合や自己参照になることがある

汎用テストの安全パターン(null 禁止の例)

-- tests/generic/not_null.sql(例)
-- args: model, column_name
with src as (
  select * from {{ model }}
)
select
  count_if({{ column_name }} is null) as null_cnt
from src
-- this はテストノード(出力先)。集計結果がここに保存されます。

フックと ephemeral: どこで this が使えるか

pre-hook/post-hook(モデル/スナップショット/シード)では this が利用できます。たとえば post-hook で権限付与や統計更新を this に対して行うのが定番です。

ephemeral モデルは物理オブジェクトを作らないため、内部で this を使うのは避けます。ephemeral は上流モデルにインライン展開され、明示的な Relation と結びつかないためです。

  • post-hook 例: grant select on {{ this }} to role ...
  • シードにもフックがあり、this はシードで作られたテーブルを指す
  • ephemeral 内で this は意味を持たないので設計を見直す(必要なら materialized='view/table')

post-hook での権限付与(Snowflake の例)

-- models/dim_customers.sql
{{ config(
  materialized='table',
  post_hook=[
    "grant select on {{ this }} to role ANALYST"
  ]
) }}

select * from {{ ref('stg_customers') }}

マクロと run-operation: this が未定義のときの対処

dbt run-operation でマクロを単体実行する場合、現在ノードの文脈がないため this は未定義です。Relation を扱いたい場合は引数で database/schema/identifier を受け取り、adapter.get_relation などで解決します。

マクロをモデルから呼ぶ場合は this が有効ですが、汎用マクロとしての再利用性を高めるには、Relation を明示的な引数として受け取る設計が安全です。

  • run-operation では this を前提にしない
  • adapter.get_relation で既存 Relation を取得、存在しなければ作成ロジックを分岐
  • 引数に Relation 文字列や構成要素(db/schema/id)を渡す設計が堅牢

run-operation 向け: Relation を明示引数で扱う

-- macros/admin.sql
{% macro drop_if_exists(database, schema, identifier) %}
  {% set rel = adapter.get_relation(database=database, schema=schema, identifier=identifier) %}
  {% if rel is not none %}
    {{ adapter.drop_relation(rel) }}
  {% else %}
    {{ log('relation not found: ' ~ database ~ '.' ~ schema ~ '.' ~ identifier, info=True) }}
  {% endif %}
{% endmacro %}

-- 例: dbt run-operation drop_if_exists --args '{"database": "ANALYTICS", "schema": "CORE", "identifier": "OLD_TABLE"}'

試験対策: よくある混乱点と確認チェック

Analytics Engineer 試験では、ref/source/this の役割分担、incremental における this の使いどころ、generic test での this と model の違いが頻出です。

「this は常に現在ノード」「ref は依存を解決して DAG を形成」「source は外部系を明示」という基本を押さえ、フック/マクロの文脈で this が未定義になり得る点を説明できるようにしておきましょう。

  • this は Relation、target はメタ(Relation ではない)
  • generic test: データ参照は model、結果の書き出し先が this
  • incremental: MERGE/DELETE の対象に {{ this }} を使う(方言差はアダプタが処理)
  • ephemeral で this を使わない
  • run-operation では this を期待しない(引数必須)

属性確認スニペット(学習用)

-- models/_debug_this.sql(学習時に役立つ)
select
  '{{ this }}' as relation,
  '{{ this.database if this is not none else "" }}' as db,
  '{{ this.schema if this is not none else "" }}'   as sch,
  '{{ this.identifier if this is not none else "" }}' as id

問題で確認

Analytics Engineer

問題 1

incremental モデルで増分実行時、既存テーブルに対して安全に MERGE を行いたい。dbt の組み込み変数の使い方として最も適切なのはどれか。

  1. MERGE の対象に {{ this }} を指定し、ステージング側は CTE/サブクエリで参照する
  2. MERGE の対象に {{ ref('stg_table') }} を指定する
  3. MERGE の対象を文字列連結で target.database || '.' || target.schema || '.' || 'table' として手書きする
  4. MERGE の対象に {{ source('raw','table') }} を指定する

正解: A

incremental モデルでは、既存の自身の Relation を指す {{ this }} を MERGE 対象に置くのが正解。ref や source は別リソースを参照し、target は Relation ではないため不適切。手書きの文字列連結はアダプタのクォート/完全修飾処理を回避してしまい危険。

よくある質問

this はどのファイル種類で使えますか?

モデル、スナップショット、テスト SQL、フック(pre/post)で利用できます。シードそのものの CSV では使えませんが、シードに紐づくフック内では使えます。run-operation で単体実行するマクロには this は入りません。

BigQuery や Snowflake などアダプタごとに this の扱いは変わりますか?

this の意味(現在ノードの Relation)は共通で、レンダリング時の完全修飾やクォートはアダプタが適切に処理します。BigQuery は project.dataset.table、Snowflake は database.schema.identifier といった違いはありますが、{{ this }} をそのまま使えば問題ありません。

generic test で this を使うと対象データを参照できますか?

いいえ。generic test では this はテストノード(結果出力先)を指し、被検モデルは model で参照します。被検データの読み出しは {{ model }} を使ってください。

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

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の記事一覧 (100件)
© 2026 NicheeLab All rights reserved.