dbt 模型的 dbt_utils.get_column_values() 的替代解决方案

问题描述 投票:0回答:1

我试图在 dbt 模型中设置一个变量。

但是,我正在努力克服遇到的问题。根据我的理解,dbt_utils.get_column_values() 不适用于 CTE,但是为了克服这个问题,我构建了一个辅助模型来模拟 cte 并构建一个表。

从这个表中(参见下面的打印截图),我想获取字符串之间的最大级别,级别将由 / 分割

为此我构建了这个模型:

--/models/dim_product/stg/stg_aux_calculate.sql

select max(LENGTH(VALUE) - LENGTH(REPLACE(VALUE, '/', '')))::integer as max_splits
from {{ source('schema', 'category_tbl') }}

这将生成此表(使用雪花):

从这里我创建一个新模型,想要选择值 5 将其设置为变量

 -- will need to add 1 to account for the original string (tackle after)
 --/models/dim_product/stg/stg_category_model.sql

{%- set max_splits = dbt_utils.get_column_values(
    table = ref('stg_aux_calculate'), 
    column = 'max_splits')[0] -%}

with split_values as (
    select
        value_id,
        value,
        {% for i in range(1, max_splits) %}
            split_part(value, '/', {{ i }}) as value_component_{{ i }},
        {% endfor %}
        ATTRIBUTE_ID,
        ENTITY_ID,
        STORE_ID
    from {{ source('schema', 'category_tbl') }}
)

select
    value_id,
    value,
    {% for i in range(1, max_splits) %}
        max(value_component_{{ i }}) as value_component_{{ i }}{% if not loop.last %},{% endif %}
    {% endfor %}
    ,
    ATTRIBUTE_ID,
    ENTITY_ID,
    STORE_ID
from split_values
group by value_id,value, ATTRIBUTE_ID, ENTITY_ID, STORE_ID 

我得到的错误是

TypeError: 'Undefined' object cannot be interpreted as an integer

我知道这是可行的,因为如果我用以下方法对变量进行硬编码:

{% set max_splits = 6 %}

它将返回我所期望的:

在雪花上,stg_aux_calculate.sql 模型是这样创建的

    create or replace view DEV_etc.DBT_my_name_xyz.stg_aux_calculate(
    MAX_SPLITS
) as (
    select max(LENGTH(VALUE) - LENGTH(REPLACE(VALUE, '/', '')))::integer as max_splits
from DEV_RAW_INT
.conf.CATALOG_CATEGORY_conf
  );

有什么建议可以克服这个问题吗?

sql jinja2 dbt
1个回答
0
投票

我已经做了一些玩具,工作示例。让我们看看:

-- my_splits_model.sql // this will just return an integer

select 5 as max_splits
-- my_downstream_model.sql

{%- set max_splits = dbt_utils.get_column_values(
      table = ref('my_splits_model'),
      column = 'max_splits'
    )[0]
-%}

-- we want to make sure that the `max_splits` variable is an actual number
{% if max_splits is number %}
select 
    '{{ max_splits }}' as this_is_my_max_splits
  {% for split in range(1, max_splits) %}
    , 'split_number_{{ split }}' as split_{{ split }}
  {% endfor %}

{% else %}
select 'hmmm' as that_is_not_a_number

{% endif %}

最后一个模型编译为:

select
    '5' as this_is_my_max_splits
  
    , 'split_number_1' as split_1
  
    , 'split_number_2' as split_2
  
    , 'split_number_3' as split_3
  
    , 'split_number_4' as split_4

如果我更新

my_splits_model.sql
以返回非整数的内容:

-- my_splits_model.sql // this will now not return an integer

select 'some text' as max_splits

然后

my_downstream_model
将编译为:

select 'hmmm' as that_is_not_a_number

因此,对于您的用例:我只是通过使用 Jinja 的内置测试

is number
确保您实际从
max_splits
set
获得的是一个实际数字。

© www.soinside.com 2019 - 2024. All rights reserved.