Sql 如何在DBT中选择bigquery表的最新分区而不扫描整个表?

Sql 如何在DBT中选择bigquery表的最新分区而不扫描整个表?,sql,google-bigquery,dbt,Sql,Google Bigquery,Dbt,为了节省查询成本,我尝试从BigQuery表中选择最新的分区,而不扫描DBT模型中的整个表 DBT不允许在数据模型中使用分号,因此使用DECLARE+SET脚本语句无法按建议工作 DBT有一个sql_头宏,允许在头中设置一些变量,但该头不接受对数据模型的引用,或者至少没有编译以下代码: {{ config( sql_header=" DECLARE latest_partition_date DATE; DECLARE latest_load_timestamp TIMEST

为了节省查询成本,我尝试从BigQuery表中选择最新的分区,而不扫描DBT模型中的整个表

DBT不允许在数据模型中使用分号,因此使用
DECLARE
+
SET
脚本语句无法按建议工作

DBT有一个sql_头宏,允许在头中设置一些变量,但该头不接受对数据模型的引用,或者至少没有编译以下代码:

{{ config(
  sql_header="  DECLARE latest_partition_date DATE;
  DECLARE latest_load_timestamp TIMESTAMP;
  SET latest_partition_date = (SELECT MAX(_PARTITIONDATE) FROM {{ ref("model") }} );
  SET latest_load_timestamp = (SELECT MAX(loaded_at) FROM {{ ref("model") }} WHERE _PARTITIONDATE = latest_partition_date);"
) }}

-- set the main query
SELECT * FROM {{ ref("model") }}
WHERE 
-- Select the latest partition to reduce 'Bytes processed' for loading the query.
_PARTITIONDATE = latest_partition_date
-- Select the latest load within the latest partition to get only one duplicate of data.
AND loaded_at = latest_load_timestamp
我需要用标准SQL解决这个问题


其他建议的方法包括设置
,其中_PARTITIONDATE=CURRENT_DATE()
或使用
DATE\u SUB(CURRENT_DATE(),3)
,但这些方法并不满足要求,因为数据加载中断是不可预测的,只有动态选择最新的才会起作用。这可能吗?

您可以在另一个查询中执行此操作,并将结果作为一个变量,如下所示:

    {%- call statement('max_partition', fetch_result=True) -%}
      SELECT MAX(_PARTITIONDATE) FROM {{ ref("model") }} )
    {%- endcall -%}

    {%- set max_date = load_result('max_partition')['data'][0][0] -%}

    SELECT * FROM {{ ref("model") }}
    WHERE 
    _PARTITIONDATE = {{ max_date }}

因为最初的问题是关于日期的,所以缺少正确的数据类型转换

最后,我认为转换到正确的数据类型需要在jinja中完成,而不是使用SQL,以便查询接受正确的变量。另外,
{{max_date}}
需要引号

我找到的最终解决方案是:


{%- call statement('max_partition_date_query', True) -%}
  SELECT MAX(_PARTITIONDATE) as max_partition_date FROM {{ ref('model') }}
{%- endcall -%}

{%- set max_timestamp = load_result('max_partition_date_query')['data'][0][0] -%}
{%- set max_date = max_timestamp.strftime('%Y-%m-%d') -%}

select * FROM {{ ref('model') }}
WHERE _PARTITIONDATE = '{{ max_date }}'

当我运行此命令时,会收到错误消息:
运算符没有匹配的签名=参数类型:DATE,INT64。支持的签名:ANY=ANY
。这可能是因为
\u PARTITIONDATE
的类型是
DATE
,但它的计算结果似乎是and INT。您知道如何解决这个问题吗?那么您可能需要强制转换它,以便从{ref(“model”)}中选择强制转换(日期(MAX(\u PARTITIONDATE))作为字符串)来检索值,也许您需要再次强制转换它,以便在主查询中使用它。我有一个使用
时间戳
列的类似示例,但我没有尝试使用
\u PARTITIONDATE
我尝试强制转换,但在编译时bgiquery忽略了这一点,仍然继续强制变量为整数。我得到的解决方案需要在jinja内进行转换