繁体   English   中英

如何在 BigQuery UDF 体内声明变量?

[英]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中使用DECLARESET的问题,您必须在代码开头声明和设置变量。 然后,将其作为参数传递给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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM