dbt Jinja环境下如何从返回变量中提取目标数字值
dbt Jinja提取statement返回值中数字的正确方案
问题说明
原有查询代码:
{%- call statement('my_statement', fetch_result=True) -%} select max(CAST(updated AS bigint)) as val from table_1 {%- endcall -%} {%- set my_var = load_result('my_statement')['data'] -%} {{ return(my_var) }}
执行后返回结果结构为:
[(Decimal('1655275144000'),)]
直接写链式索引load_result('my_statement')['data'][0][0]取值会触发报错,但同样的索引逻辑在原生Python环境可以正常运行。
报错原因
load_result()返回的data不是原生Python的嵌套列表/元组,是dbt依赖的agate库封装的行集合对象,嵌套的行是自定义Row类型,Jinja对这类非原生对象的多层链式索引访问支持有缺陷,无法正确解析连续的索引操作,才会抛出错误。
解决方法
方法1:分步索引取值(全版本兼容,最稳妥)
把链式索引拆成两步写,先拿第一行,再拿行里的第一个值,最后转成普通整数类型即可:
{%- call statement('my_statement', fetch_result=True) -%} select max(CAST(updated AS bigint)) as val from table_1 {%- endcall -%} {# 先取结果集 #} {%- set result_rows = load_result('my_statement')['data'] -%} {%- set first_row = result_rows[0] -%} {# 取行内第一个字段,转成普通整数,移除Decimal类型 #} {%- set max_updated = first_row[0] | int -%} {{ return(max_updated) }}
方法2:用run_query快捷写法(dbt 0.19.0及以上版本可用)
新版本dbt可以直接用run_query封装好的方法取结果,支持按列索引/列名取值,代码更清晰:
{%- set result = run_query("select max(CAST(updated AS bigint)) as val from table_1") -%} {# 取第一列的第一个值,转整数 #} {%- set max_updated = result.columns[0].values()[0] | int -%} {{ return(max_updated) }}
小提示:返回值默认是Decimal类型,不管用哪种方法取值,都建议加
| int过滤器转成普通整数,避免后续做逻辑判断、字符串拼接时出现类型不兼容的问题。
内容的提问来源于stack exchange,提问作者Aleksandra
相关产品推荐
相关产品推荐

