iT邦幫忙

2024 iThome 鐵人賽

DAY 4
2

上一篇介紹了建立 macro 的情境及如何撰寫,本篇將探討 dbt 內建的 macros。

dbt 提供了眾多內建 macros,大幅提升了代碼的可重用性和維護性。dbt 官方文件列出了完整的內建 macros 清單,並詳細說明了它們的用法。我將介紹幾個在日常工作中最常用、最實用的 macros。

ref

ref 是用來建立 model 間的上下游關聯。例如,計算會員平均交易金額的 model 中使用了會員和交易表,可以用 ref('會員表') 和 ref('交易表') 來表示這兩個表是該 model 的上游表。在執行 dbt run 時,dbt 會先運行會員和交易表,然後才運行計算會員平均交易金額的 model。

透過 ref 建立上下游關係後,後續建立好 dbt docs 就能在其中清楚地看到這三個 models 之間的關聯。

SELECT
	m.name,
	AVG(t.amount) AS avg_amount
FROM
	ref('transactions') t # ref 裡面放 model 名稱
LEFT JOIN
	ref('members') m
ON
	t.member_id = m.id
GROUP BY
	name

ref 回傳值是一個 Relation 物件,包含 database、schema 和 identifier 屬性。因此,在編譯後,dbt 能夠確定 ref 所指的表對應到資料庫中的具體位置。

# members 表放在 db.datamart.members 中
# transactions 表放在 db.datamart.transactions 中
# 上面 model compile 會變以下 query
SELECT
	m.name,
	AVG(t.amount) AS avg_amount
FROM
	`db.datamart.transactions` t 
LEFT JOIN
	`db.datamart.members` m
ON
	t.member_id = m.id
GROUP BY
	name

source

source 和 ref 很相似,但有一個關鍵區別:ref 用於指示 dbt 該 model 依賴哪些上游 model,而 source 則用於指示該 model 使用哪些來源表(需要先在 yaml 文件中定義 source 表)。

通過使用 source 來引用來源表,我們同樣可以建立上下游關係。就能夠利用 dbt docs 來清晰地查看來源表與 model 之間的關聯。

# source.yml
version: 2

sources:
  - name: mysql # source 名稱
    schema: mysql
    database: db
    tables:
      - name: members
      - name: transactions
SELECT
	...
FROM
	{{ source('mysql', 'members') }} # 第一個參數填入 source 名稱,第二個參數填入表名稱

編譯時,dbt 會根據 source.yml 檔案中指定的 schema 和 database 來構建出來源表在資料倉儲中的完整名稱。

# 編譯結果
SELECT
	...
FROM
	`db.mysql.members`

config

config 可以在 model 中設定該 model 的 database, schema, alias, materialized 等屬性(會覆蓋掉在 dbt_project.yml 的設定),詳細可設定的參數和不同層級 config 設定可參考 dbt 文件

config macro 可以根據 model 的 materialized 填入額外參數(未來提到 materialization 會更詳細說明),例如 model materialized 設為 incremental,config 可以多填入 unique_key 參數(incremental 的選填參數),unique_key 用途可參考 incremental 說明,這邊就不多贅述。

{{
    config(
        materialized='incremental', # 定義 model materialized 類型
        unique_key='date_day' # incremental 的選填參數
    )
}}

select
    date_trunc('day', event_at) as date_day,
    count(distinct user_id) as daily_active_users

from {{ ref('app_data_events') }}


{% if is_incremental() %}

  where date_day >= (select coalesce(max(event_time), '1900-01-01') from {{ this }})

{% endif %}

group by 1

以上介紹了 3 個常用 dbt 內建 macro,下篇會繼續介紹內建 macro 以及如何根據使用情境來改寫。

參考


上一篇
Macro 基礎用法
下一篇
dbt 內建 macro(下)
系列文
dbt 修煉之路30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言