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

BigQuery UDF使用ARRAY_AGG报错的解决方案咨询

BigQuery中封装ARRAY_AGG逻辑为UDF报错的解决方法

问题描述

我尝试在BigQuery中创建UDF将多行数据压缩为单行,编写的函数代码如下:

CREATE OR REPLACE FUNCTION function_name(to_compress_column INT64, order_by_column INT64) AS (
    TO_JSON_STRING(
           ARRAY_AGG(
                IFNULL(to_compress_column,-1) RESPECT NULLS
                ORDER BY order_by_column
                    )
                  )
    );

执行时触发错误:ARRAY_AGG not allowed in SQL function body。我试过用SELECT和UNNEST,但输入不是数组,没能解决问题。

输入表结构及数据

visitsplace_iddatehour
23abc1232022-01-014
20abc1232022-01-012
19abc1232022-01-013
24abc1232022-01-011
26abc1232022-01-015
18abc4562022-01-012
20abc4562022-01-013
17abc4562022-01-011

期望输出

visitsplace_iddate
[24,20,19,23,26]abc1232022-01-01
[17,18,20]abc4562022-01-01

我已经知道用以下SQL可以实现需求:

SELECT TO_JSON_STRING(ARRAY_AGG(IFNULL(visits,-1) RESPECT NULLS
  ORDER BY hour)) visits, 
  place_id, 
  date 
  from input_table
  group by place_id, date

但因为要处理大量表,不想重复写这段聚合逻辑,希望封装成UDF后用简化的查询:

SELECT function_name(visits,hour) visits, 
      place_id, 
      date 
      from input_table
      group by place_id, date

请问怎么解决UDF里用ARRAY_AGG报错的问题?


原因分析

BigQuery的标量SQL UDF(即你编写的这种单行函数)不支持聚合函数(如ARRAY_AGG),因为标量UDF的设计目标是处理单条行的输入,而聚合函数是对分组后的多行数据进行计算,两者执行逻辑不兼容。

解决方法

方法1:使用表值函数(TVF)

表值函数可以处理分组后的数据集,返回结构化结果。你可以创建一个接受分组行数组作为输入的TVF:

CREATE OR REPLACE FUNCTION my_dataset.aggregate_and_jsonify(
  input_data ANY TYPE
)
RETURNS STRING
AS ((
  SELECT TO_JSON_STRING(ARRAY_AGG(IFNULL(visits_col, -1) RESPECT NULLS ORDER BY hour_col))
  FROM UNNEST(input_data) AS row
));

使用时需要先将分组内的行打包成数组传入:

SELECT 
  my_dataset.aggregate_and_jsonify(ARRAY_AGG(STRUCT(visits AS visits_col, hour AS hour_col))) AS visits,
  place_id,
  date
FROM input_table
GROUP BY place_id, date;

方法2:使用BigQuery宏(推荐)

宏是更适配该场景的方案,它会在查询解析阶段直接替换为对应SQL代码,完全复用聚合逻辑,写法和你期望的简化查询几乎一致:

CREATE OR REPLACE MACRO my_dataset.aggregate_visits(col_to_compress, order_col) AS (
  TO_JSON_STRING(ARRAY_AGG(IFNULL(col_to_compress, -1) RESPECT NULLS ORDER BY order_col))
);

使用宏的查询语句完全符合你的需求:

SELECT 
  my_dataset.aggregate_visits(visits, hour) AS visits,
  place_id,
  date
FROM input_table
GROUP BY place_id, date;

宏的优势在于仅做代码替换,无额外执行开销,且保留原SQL的执行计划,适合批量处理大量表的场景。


内容的提问来源于stack exchange,提问作者Kartikey Mullick

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 09:24:27