[英]How to declare variable inside BigQuery UDF body?
我正在尝试在 BigQuery 上创建一个带有 while 循环的 UDF function,但我没有在文档中看到任何语法指南,它专门针对这种情况,也没有解决 UDF 主体中的变量声明。
上下文:我正在尝试构建一个 function 以将标题大小写应用于字符串。
我试过:
CREATE CREATE OR REPLACE FUNCTION mydataset.title_case(word STRING) as (
DECLARE i INT64;
SET i = ARRAY_LENGTH(SPLIT(word, " "));
...
);
但是它不喜欢 UDF 主体中的 DECLARE 或 SET。 正确的语法是什么?
关于如何在UDF中使用DECLARE和SET的问题,您必须在代码开头声明和设置变量。 然后,将其作为参数传递给UDF ,语法为;
DECLARE x ARRAY <String>;
SET x = (SELECT ARRAY_LENGTH(SPLIT(word, " ")) FROM `project_id.dataset.table`);
CREATE CREATE OR REPLACE FUNCTION mydataset.title_case(word STRING, x INT64) as (
#your function...
);
请注意,变量是根据表中的值设置的,使用SELECT 。 此外,您将它作为参数传递给UDF 。
此外,我能够创建一个 JavaScript UDF 以将标题大小写应用于没有 SET 和 DECLARE 的字符串。 我只使用过 JS 的内置方法。 您可以按如下方式使用它:
CREATE TEMP FUNCTION title_case(str String)
RETURNS string
LANGUAGE js AS """
str = str.split(' ');
for(var i = 0; i < str.length; i++){
str[i] = str[i].charAt(0).toUpperCase() + str[i].slice(1);
}
return str.join(' ');
""";
WITH data AS (
SELECT "jack sparrow" AS name
)
SELECT title_case(name) as new_name FROM data
和 output,
Row new_name
1 Jack Sparrow
上下文:我正在尝试构建一个 function 以将标题大小写应用于字符串。
而不是直接回答问题 - 我宁愿先解决我认为促使问题被问到的问题
从我在 SO 上的经验可以明显看出,OP 经常会问一些字面上的问题,帮助他们 go 错误的方向。 在很多情况下,这是一种悲伤的经历,因为你明白你并没有为这样的人提供好的帮助,而是恰恰相反,我多次参与其中感到内疚,因为并不总是很清楚真正的用例是什么,所以有没有太多选择可以帮助而不是回答被问到的确切问题
我认为在这种情况下——上面的问题很好地暗示了真正的目的/用例——所以正如我已经说过的,我想回答它(用例)
在大多数情况下你真的不需要做循环 - 你应该尝试以 sql 的方式实现事物 - 基于集合!
所以,提示在下面的语句中
上下文:我正在尝试构建一个 function 以将标题大小写应用于字符串。
处理title case function的简单方法如下
#standardSQL
CREATE TEMP FUNCTION TitleCase(text STRING) AS ((
SELECT STRING_AGG(UPPER(SUBSTR(part, 1, 1)) || SUBSTR(part, 2), ' ' ORDER BY OFFSET)
FROM UNNEST(SPLIT(text, ' ')) part WITH OFFSET
));
SELECT text,
TitleCase(text) transformed_text
FROM `project.dataset.table`
您可以在上面使用虚拟数据进行测试,如下例所示
#standardSQL
CREATE TEMP FUNCTION TitleCase(text STRING) AS ((
SELECT STRING_AGG(UPPER(SUBSTR(part, 1, 1)) || SUBSTR(part, 2), ' ' ORDER BY OFFSET)
FROM UNNEST(SPLIT(text, ' ')) part WITH OFFSET
));
WITH `project.dataset.table` AS (
SELECT 1 id, "google cloud platform" AS text UNION ALL
SELECT 2, "o'brian"
)
SELECT text,
TitleCase(text) transformed_text
FROM `project.dataset.table`
output 如下
Row text transformed_text
1 google cloud platform Google Cloud Platform
2 o'brian O'brian
如您所见,您最初使用空格作为分隔符来拆分文本的方法并不是最好的方法O'brian
没有将b
大写
要解决这个问题 - 您可以使用以下方法
#standardSQL
CREATE TEMP FUNCTION TitleCase(text STRING) AS ((
SELECT STRING_AGG(char, '' ORDER BY OFFSET)
FROM (
SELECT IF(REGEXP_CONTAINS(LAG(char) OVER(ORDER BY OFFSET), r'\w'), char, UPPER(char)) char, OFFSET
FROM UNNEST(SPLIT(text, '')) char WITH OFFSET
)
));
SELECT text,
TitleCase(text) transformed_text
FROM `project.dataset.table`
现在,当应用于相同的虚拟数据时 - 结果更合适
Row text transformed_text
1 google cloud platform Google Cloud Platform
2 o'brian O'Brian
注意:以上只是一个(或两个)示例,说明如何避免无效的基于 cursor 的处理,而是在一个(基于集合的)回合中完成所有操作
对于到这里来查找如何在 function 内声明和设置变量的人(如问题标题所示),答案是您不能使用 DECLARE 和 SET 这样做,但没有必要在外部声明(这不是可以使用永久函数):可以使用 WITH 语句。
假设您希望func1(phrase_in)
从table1
返回结果,其中phrase
值与phrase_in
的长度相同。 这可能被尝试为:
CREATE OR REPLACE TABLE FUNCTION mydataset.func1(phrase_in STRING) as (
DECLARE phrase_len INT64;
SET phrase_len = ARRAY_LENGTH(SPLIT(phrase_in, " "));
SELECT phrase, date, user
FROM `mydataset.table1`
WHERE ARRAY_LENGTH(SPLIT(phrase, " ")) = phrase_len
);
这将引发错误,但可以使用
CREATE OR REPLACE TABLE FUNCTION mydataset.func1(phrase_in STRING) as (
WITH phrase_len AS (
SELECT ARRAY_LENGTH(SPLIT(phrase_in, " ")) x
)
SELECT phrase, date, user
FROM `mydataset.table1`
WHERE ARRAY_LENGTH(SPLIT(phrase, " ")) = (SELECT x FROM phrase_len)
);
对于这样一个简单的例子,这显然有点过分了,但是当phrase_len
变量不是通过输入变量的简单 function 计算而是使用来自其他表的 SELECT 语句计算的,并且可能在其中多次重复使用时,我使用了这种方法UDF(因此想要声明以避免多次进行相同的子查询)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.