BigQuery - 在连接谓词中使用 SQL UDF

Lio*_*ior 6 google-bigquery

我在运行左连接时尝试使用 SQL UDF,但出现以下错误:

连接谓词中的子查询应该只依赖于一个连接方。

查询是:

CREATE TEMPORARY FUNCTION game_match(game1 STRING,game2 STRING) AS (
  strpos(game1,game2) >0
);

SELECT 
  t1.gameId 
  FROM `bigquery-public-data.baseball.games_post_wide` t1
  left join `bigquery-public-data.baseball.games_post_wide` t2 on t1.gameId=t2.gameId and game_match(t1. gameId, t2.gameId)
Run Code Online (Sandbox Code Playgroud)

内联编写条件时(strpos(t1. gameId, t2. gameId) >0),查询工作而不是函数调用。

这个特定函数是否有问题,或者通常情况下连接谓词不支持 SQL UDF(出于某种原因)?

Ell*_*ard 6

您可以在问题跟踪器上提交功能请求以完成这项工作。这是查询计划/优化的限制;对于某些背景,BigQuery 会转换函数调用,以便查询的逻辑表示如下:

SELECT 
  t1.gameId 
FROM `bigquery-public-data.baseball.games_post_wide` t1
left join `bigquery-public-data.baseball.games_post_wide` t2
on t1.gameId=t2.gameId
  and (SELECT strpos(game1,game2) > 0 FROM (SELECT t1.gameId AS game1, t2.gameId AS game2))
Run Code Online (Sandbox Code Playgroud)

BigQuery 像这样转换 SQL UDF 调用的原因是它需要避免多次计算输入。虽然在这种特殊情况下这不是问题,但如果您在 UDF 正文中多次引用其中一个输入,则会有所不同,例如考虑这个 UDF:

CREATE TEMP FUNCTION Foo(x FLOAT64) AS (x - x);
SELECT Foo(RAND());
Run Code Online (Sandbox Code Playgroud)

如果 BigQuery 直接内联表达式,你会得到这样的结果:

SELECT RAND() - RAND();
Run Code Online (Sandbox Code Playgroud)

结果不会为零,鉴于 UDF 的定义,这是出乎意料的。

在大多数情况下,BigQuery 的逻辑优化将如上所示的更复杂的子选择转换为更简单的形式,假设这样做不会改变查询的语义。但是,在这种情况下并没有发生这种情况,因此出现了错误。