You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DBT for循环使用数字作为变量时PostgreSQL union报错问题问询

问题根因

你遇到的两个报错分别来自Jinja语法使用不当和传参类型不匹配:

  • 循环声明{% for 't_'~dpid in dpids %}属于非法Jinja语法,不能在循环变量定义段做字符串拼接操作
  • union_all('t_'~dpids)的入参是拼接后的字符串,而dbt的union_all宏要求入参为列表类型,宏会自动遍历入参的每个元素生成union语句,你传入字符串后宏就会遍历每个字符,才会出现逐字符拆分的错误SQL。
解决方案

正确的实现逻辑是先预处理生成带t_前缀的CTE名称列表,再分别用于CTE定义和union操作,示例代码如下:

{{ config(materialized='table') }}

{%- set dpids = ["123","1234"] -%}
{# 构造带t_前缀的CTE名称列表 #}
{%- set cte_names = [] %}
{% for dpid in dpids %}
    {%- do cte_names.append('t_' ~ dpid) %}
{% endfor %}

WITH
{% for idx in range(dpids | length) %}
    {{ cte_names[idx] }} AS (
        SELECT *
            FROM {{ ref('table_name') }} b
            WHERE b.create_ts > ({{ get_last_load_timestamp('table_name', dpids[idx]) }}) 
            AND b.dpid = '{{ dpids[idx] }}'
    ){% if not loop.last %},{% endif %}
{% endfor %}

{# 传入处理好的CTE列表生成union语句 #}
{{ union_all(cte_names) }}

如果你的dbt版本支持prefix过滤器,可以简化CTE列表的构造逻辑:

{%- set cte_names = dpids | map('prefix', 't_') | list -%}

最终生成的SQL会自动给CTE加前缀,完全符合PostgreSQL语法要求:

WITH
t_123 AS (
    ... WHERE dpid = '123'
),
t_1234 AS (
    ... WHERE dpid = '1234'
)
select * from t_123 union all select * from t_1234

内容的提问来源于stack exchange,提问作者Boris B

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 03:24:04