BigQuery 是不是支持分析用户定义的函数?

Posted

技术标签:

【中文标题】BigQuery 是不是支持分析用户定义的函数?【英文标题】:Does BigQuery support Analytic User-Defined Functions?BigQuery 是否支持分析用户定义的函数? 【发布时间】:2020-11-26 16:53:42 【问题描述】:

BigQuery 支持:

    SQL 和 javascript 中的User Defined Functions (UDF)。 Analytic functions 计算一组行的值并为每一行返回一个结果。这些函数可以与OVER 子句一起使用。有一组预定义的分析函数。

问题 #1:“BigQuery 是否支持分析用户定义的函数?”

这背后的动机是我想实现 Python pandas 代码中常见的split-apply-combine 模式。这对于组内归一化和使用组统计的其他转换可能很有用。

我在 Standart SQL 中做了一个小测试:

create or replace function `mydataset.mylen`(arr array<string>) returns int64 as (
  array_length(arr)
);

WITH Produce AS
 (SELECT 'kale' as item, 23 as purchases, 'vegetable' as category
  UNION ALL SELECT 'orange', 2, 'fruit'
  UNION ALL SELECT 'cabbage', 9, 'vegetable'
  UNION ALL SELECT 'apple', 8, 'fruit'
  UNION ALL SELECT 'leek', 2, 'vegetable'
  UNION ALL SELECT 'lettuce', 10, 'vegetable')
SELECT 
  item, 
  purchases, 
  category, 
  `mydataset.mylen`(item) over (mywindow) as windowlen
FROM Produce
window mywindow as (
  partition by category
)

当我运行上面的代码时,我得到:

查询错误:函数 mydataset.mylen 在 [16:3] 不支持 OVER 子句

因此,如果 BigQuery 确实支持分析 UDF,问题 #2:“如何实现 UDF 以使其支持 OVER 子句?”

【问题讨论】:

【参考方案1】:

你已经非常接近解决问题了:)

对于答案的读者来说,BigQuery 不支持用户定义的聚合/分析函数,因此模拟它的一种方法是编写一个接受数组作为输入的标量 UDF。然后在查询中,使用 array_agg() 函数将数据打包为 UDF 的输入,(这是问题中缺少的步骤)。

  `mydataset.mylen`(item) over (mywindow) as windowlen

=>

  `mydataset.mylen`(array_agg(item) over (mywindow))  as windowlen

【讨论】:

据我了解,mydataset.mylen 函数分别应用于每一行,并将分区组作为参数。这就是为什么函数不必返回类似大小的数组的原因——它是为每一行调用的,而不是一组行。 这太棒了!使用这种方法,我现在可以将我的 pandas 代码传输到 BigQuery。我看到的主要区别是没有矢量化:我将计算每一行的分区组的聚合。猜猜这是 BigQuery 的优化器能够解决的小问题。 不确定你的预期输出是什么,如果你只需要一组值,你应该使用 GROUP BY 类别而不是带有类别的窗口函数。但 UDF 在这两种情况下都是相同的。

以上是关于BigQuery 是不是支持分析用户定义的函数?的主要内容,如果未能解决你的问题,请参考以下文章

如何创建使用用户定义函数的 BigQuery 视图?

使用 SQL 查询从 BigQuery 用户定义函数返回值

JavaScript 中的 BigQuery 用户定义函数不会修剪分区

使用用户定义的函数在 BigQuery 数据集中插入海量数据时如何优化性能

BigQuery 中的分析函数问题

将 STRUCT 的 ARRAY 传递给标准 BigQuery SQL 的用户定义函数