Jinja和宏
相关文档¶
简介¶
在dbt中,您可以将SQL与Jinja(一种模板语言)结合使用。
使用Jinja可以将您的dbt项目变成SQL的编程环境,使您能够做SQL中通常做不到的事情。例如,使用Jinja,您可以:
- 在SQL中使用控制结构(例如
if语句和for循环) - 在生产环境部署的dbt项目中使用环境变量
- 更改基于当前target构建项目的方式.
- 对一个查询的结果进行操作以生成另一个查询,例如:
- 返回付款方式列表,以便按付款方式创建小计列(透视图)
- 返回两个关系中的字段列表,并以相同的顺序选择它们,以便更容易将它们合并在一起
- 将SQL的片段抽象为可重用的宏,这些类似于大多数编程语言中的函数.
实际上,如果你已经使用{{ ref() }}函数, 那么你就已经在使用Jinja!
Jinja可以用于dbt项目中的任何SQL, 包括模型, 分析, 测试, 甚至 hooks.
准备好开始使用Jinja和宏了吗?
查看使用Jinja教程,了解在模型中使用Jinja并将其转化为宏的分步示例!
开始¶
Jinja¶
以下是一个利用Jinja的dbt模型示例:
{% set payment_methods = ["bank_transfer", "credit_card", "gift_card"] %}
select
order_id,
{% for payment_method in payment_methods %}
sum(case when payment_method = '{{payment_method}}' then amount end) as {{payment_method}}_amount,
{% endfor %}
sum(amount) as total_amount
from app_data.payments
group by 1
此查询将被编译为:
select
order_id,
sum(case when payment_method = 'bank_transfer' then amount end) as bank_transfer_amount,
sum(case when payment_method = 'credit_card' then amount end) as credit_card_amount,
sum(case when payment_method = 'gift_card' then amount end) as gift_card_amount,
sum(amount) as total_amount
from app_data.payments
group by 1
你可以根据语言使用的分隔符来识别Jinja,我们称之为“curlies”:
- 表达式
{{ ... }}: 表达式用来输出字符串. 你可以使用表达式引用变量并调用宏. - 语句
{% ... %}: 用于控制流,例如,设置for循环和if语句,或定义宏。 - 注释
{# ... #}: Jinja注释用于阻止编译注释中的文本
在dbt模型中使用时,Jinja需要编译为有效的查询。要检查Jinja编译的SQL是什么:
- 使用dbt Cloud: 单击“编译”按钮,在“编译的SQL”窗口中查看编译的SQL
- 使用dbt CLI: 从命令行运行
dbt compile,然后在target/compiled/{project name}/目录中打开已编译的SQL文件。在代码编辑器中使用分屏,可以同时打开两个文件。
宏¶
宏在Jinja中的代码片段可以多次重复使用——它们类似于其他编程语言中的“函数”,如果您发现自己在多个模型中重复代码,则非常有用。宏在.sql文件中定义,通常在宏目录中。
宏文件可以包括一个或多个宏,以下为示例:
{% macro cents_to_dollars(column_name, precision=2) %}
({{ column_name }} / 100)::numeric(16, {{ precision }})
{% endmacro %}
一个模型可以这样使用这个宏
它会被 编译 成:
从包中使用宏¶
许多有用的宏也被组合成了包-我们最流行的包是dbt-utils.
将包安装到项目中后,您可以在自己的项目中使用任何宏-确保您通过在宏前面加上包名称来限定宏:
select
field_1,
field_2,
field_3,
field_4,
field_5,
count(*)
from my_table
{{ dbt_utils.group_by(5) }}
您也可以在自己的项目中通过在宏前面加上包名称来限定宏(这主要对包作者有用)。
dbtonic Jinja¶
就像写得好的python是pythonic一样,编写得好的dbt代码也是dbtonic。
Favor readability over -ness¶
一旦你掌握了Jinja的强大之处,你就会想把每一句重复的代码抽象成一个宏!请记住,使用Jinja会使其他用户更难解释您的模型——我们建议在将Jinja与SQL混合时,即使这意味着在一些地方重复一些SQL,也要注重可读性。如果您的所有模型都是宏,那么可能值得重新评估。
利用包和宏¶
第一次写宏?检查我们是否在[dbt utils]中有开源的(https://hub.getdbt.com/dbt-labs/dbt_utils/latest/) 供你使用,以节省时间。
在模型顶部设置变量¶
{% set ... %}可用于创建新变量或更新现有变量。我们建议在模型的顶部设置变量,而不是在中间写死。这是从许多其他编码语言中借鉴的一种做法,因为它有助于提高可读性,如果您需要在两个地方引用变量,它会派上用场:
-- 🙅 这也可以,不过随着代码的增长将难以维护
{% for payment_method in ["bank_transfer", "credit_card", "gift_card"] %}
...
{% endfor %}
-- ✅ 我们更推荐这样设置变量
{% set payment_methods = ["bank_transfer", "credit_card", "gift_card"] %}
{% for payment_method in payment_methods %}
...
{% endfor %}