背景:
我每周都会使用相同的架构创建一个新表,并且其名称将始终具有相同的前缀。
表格示例:
模型 1 名称:avengers_au
名字 | 出生日期 | 国籍 |
---|---|---|
xyz | 2024-01-04 | au |
abc | 2024-01-05 | au |
模型 2 名称:avengers_us
名字 | 出生日期 | 国籍 |
---|---|---|
xyz | 2024-01-04 | 我们 |
abc | 2024-01-05 | 我们 |
...等等等等
当前解决方案
每次创建新表时,我都会手动执行 UNION ALL:
SELECT
*
FROM
avengers_au
UNION ALL
SELECT
*
FROM
avengers_us
... will add manually everytime there's a new table created
问题:
dbt 有什么方法可以自动化这个过程吗?
我将为您提供我过去所做的事情的伪模板。您可以使用模型参考或基础源来执行此操作。您只需要根据您的情况稍微调整一下宏即可。另外,我的表列表是静态的。如果您的模型是动态的,您可以创建一个宏来从数据库平台的信息模式中检索列表,在模型上使用某种命名约定,您可以通过编程方式列出该列表,或者简单地在
dbt_project.yml
中更新列表(当列表发生变化时)(这就是我所做的)。
首先,我将表格/参考放入
dbt_project.yml
:
...
vars:
avengers_sources:
- model1
- model2
- model3
...
然后我有一个简单的宏,可以返回模型列表,类似于基本的
ref
宏的作用。你可以用“source”做同样的事情。
{% macro refs(var_name) %}
{% set ref_name_list = var(var_name) %}
{% set models = [] %}
{% for model in ref_name_list %}
{% do models.append(builtins.ref(model)) %}
{% endfor %}
{% do return(models) %}
{% endmacro %}
同样,如果需要,您可以将上述宏替换为查询信息模式的宏。
这是一个如何在模型中使用它进行联合的示例。同样在我的示例中,我允许包含某些模型中可能存在的可选列,但不是全部。
我的_model.sql:
WITH
{% set model_relations = refs('avengers_sources') %}
{% for model_relation in model_relations %}
{{ model_relation.identifier}}_SOURCE AS (
SELECT * FROM {{ model_relation }}
),
{% endfor %}
UNIONED AS (
{% for model_relation in model_relations %}
{%- set columns = dbt_utils.get_filtered_columns_in_relation(from=model_relation) -%}
SELECT
NAME,
DATE_BIRTH,
{% if 'NATIONALITY' in columns -%}
NATIONALITY,
{% else %}
NULL::STRING NATIONALITY,
{% endif %}
FROM {{ model_relation.identifier}}_SOURCE
{% if not loop.last %}
UNION ALL
{% endif %}
{% endfor %}
)
SELECT * FROM UNIONED