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

Edg*_*gar 7 sql google-bigquery dbt

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

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

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

{{ 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
Run Code Online (Sandbox Code Playgroud)

我需要用标准 SQL 来解决这个问题。

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

Edg*_*gar 2

由于最初的问题是处理日期,因此缺少正确的数据类型转换。

最后,我认为需要在 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 }}'
Run Code Online (Sandbox Code Playgroud)