this は「いまコンパイル・実行しているノード(モデル/スナップショット/テスト/フックなど)」を表す Relation を返す dbt の組み込み変数です。
本稿では this の仕組み、ref/source との違い、インクリメンタルでの活用、テストや run-operation での注意点を、試験で狙われやすいポイントに沿ってまとめます。
this は Jinja コンテキストで利用できる組み込み変数で、現在のノードを指すアダプタ依存の Relation オブジェクトを返します。レンダリング時には database.schema.identifier(アダプタが適切にクォート)として展開されます。
this.database / this.schema / this.identifier の各属性にアクセスできます。モデルやスナップショット、テスト、フックで利用可能ですが、ephemeral モデル内での利用は非推奨(物理オブジェクトを持たないため意味が曖昧)です。
| 構文 | 目的 | レンダリング結果の例 |
|---|---|---|
| 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 の展開
最小例: this の属性を参照する
-- models/demo_this.sql
-- 実行時に現在モデルの各構成要素を確認
select
'{{ this.database }}' as db,
'{{ this.schema }}' as sch,
'{{ this.identifier }}' as idincremental モデルでは、既存テーブル(ターゲット)と新規ステージングの突合が必要です。this は常に「自モデルの最終的な Relation」を指すため、MERGE/DELETE/INSERT の対象として安全に利用できます。
BigQuery/Snowflake/Databricks など主要アダプタは {{ this }} のクォートと完全修飾を適切に処理します。SQL 方言の差分は WHEN 句や IDENTIFIER クォートに現れますが、this 自体の役割は共通です。
増分モデルでの定番 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 %}汎用テスト(generic test)のコンテキストでは、しばしば混同が起きます。this はテスト自体(dbt が生成する一時的なテスト関係)を指し、model は被検モデル(ref で解決された Relation)を指します。
列テストを自作する場合、データを読む対象は model、出力(集計結果)の最終書き出し先は 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 はテストノード(出力先)。集計結果がここに保存されます。pre-hook/post-hook(モデル/スナップショット/シード)では this が利用できます。たとえば post-hook で権限付与や統計更新を this に対して行うのが定番です。
ephemeral モデルは物理オブジェクトを作らないため、内部で this を使うのは避けます。ephemeral は上流モデルにインライン展開され、明示的な Relation と結びつかないためです。
post-hook での権限付与(Snowflake の例)
-- models/dim_customers.sql
{{ config(
materialized='table',
post_hook=[
"grant select on {{ this }} to role ANALYST"
]
) }}
select * from {{ ref('stg_customers') }}dbt run-operation でマクロを単体実行する場合、現在ノードの文脈がないため this は未定義です。Relation を扱いたい場合は引数で database/schema/identifier を受け取り、adapter.get_relation などで解決します。
マクロをモデルから呼ぶ場合は this が有効ですが、汎用マクロとしての再利用性を高めるには、Relation を明示的な引数として受け取る設計が安全です。
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 が未定義になり得る点を説明できるようにしておきましょう。
属性確認スニペット(学習用)
-- 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 idAnalytics Engineer
問題 1
incremental モデルで増分実行時、既存テーブルに対して安全に MERGE を行いたい。dbt の組み込み変数の使い方として最も適切なのはどれか。
正解: 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 }} を使ってください。
NicheeLab編集部
データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。
dbt Model の基礎: SQL で定義する変換の最小単位
Analytics Engineer 向けに、dbt Model の定義、マテリアライゼーション、依存関係、インクリメン...
dbt Analytics Engineer 試験ガイド: 出題範囲・配点・申込の実務視点
dbt Analytics Engineer 認定の出題範囲、配点の考え方、申込から受験までの流れを、公式ドキュメントの...
dbt Cloud と dbt Core の違いと選び方:Analytics Engineer 試験に効く要点
dbt Cloud と dbt Core の機能差を、実務と資格対策の両面から整理。スケジューリング、IDE、RBAC、...
dbt プロジェクト構造ガイド: models / seeds / macros の実務レイアウト
Analytics Engineer 向けに、dbt プロジェクトのディレクトリ構造と命名規約、dbt_project....
dbt_project.yml の読み方:主要設定と命名を最短で掴む
dbt_project.yml の必須キー、命名解決(database.schema.identifier)、設定優先度...