Bỏ qua để đến nội dung

Jinja & Macros trong dbt: template hóa SQL, tái dùng logic

SQL thuần không có vòng lặp, không có hàm, không có biến. dbt thêm sức mạnh đó bằng Jinja — một ngôn ngữ template. Nhờ Jinja, SQL của bạn trở nên động, ngắn gọn và tái dùng được.

Bạn đã gặp Jinja rồi: ref(), source(), config() đều là hàm Jinja. Cú pháp:

  • {{ ... }}chèn giá trị (biểu thức).
  • {% ... %}câu lệnh (vòng lặp, điều kiện).

Giả sử cần tính tổng doanh thu cho nhiều loại sản phẩm. Thay vì gõ tay 10 dòng giống nhau:

select
khach_hang_id,
{% for loai in ['dien_thoai', 'laptop', 'phu_kien'] %}
sum(case when loai_sp = '{{ loai }}' then gia_tri else 0 end) as doanh_thu_{{ loai }}
{% if not loop.last %},{% endif %}
{% endfor %}
from {{ ref('stg_don_hang') }}
group by khach_hang_id

dbt compile đoạn trên thành SQL thuần với đủ 3 cột doanh_thu_dien_thoai, doanh_thu_laptop, doanh_thu_phu_kien. Thêm loại mới? Chỉ sửa danh sách.

Macro là đoạn SQL/Jinja đóng gói thành “hàm” để gọi lại. Đặt trong macros/:

-- macros/lam_sach_tien.sql
{% macro lam_sach_tien(cot) %}
round(coalesce({{ cot }}, 0), 0)
{% endmacro %}

Dùng trong bất kỳ model nào:

select
{{ lam_sach_tien('gia_tri') }} as gia_tri,
{{ lam_sach_tien('phi_ship') }} as phi_ship
from {{ ref('stg_don_hang') }}

Sửa quy tắc “làm sạch tiền” một chỗ → áp cho toàn bộ dự án. Đây là cách chuẩn hóa logic ở quy mô lớn.

Jinja cho phép dùng biến (var()) và biến môi trường (env_var()) — ví dụ đổi ngày bắt đầu nạp dữ liệu giữa dev/prod mà không sửa code:

where ngay_tao >= '{{ var("ngay_bat_dau", "2024-01-01") }}'

Bạn không phải tự viết mọi macro. dbt Packages là thư viện macro/model dùng chung của cộng đồng:

  • dbt_utils — bộ macro tiện ích “phải có” (tạo khóa, pivot, kiểm tra…).
  • dbt_expectations — bộ test dữ liệu phong phú.
  • Nhiều package theo nguồn (Stripe, Salesforce, GA4…) dựng sẵn model staging.

Khai báo trong packages.yml rồi dbt deps để cài.

Chia sẻ: