Google bigquery 如何在BigQueryUDF主体中声明变量?

Google bigquery 如何在BigQueryUDF主体中声明变量?,google-bigquery,user-defined-functions,Google Bigquery,User Defined Functions,我试图在BigQuery上创建一个带有while循环的UDF函数,但我在文档中没有看到任何语法指南,这些指南专门针对这种情况,也没有在UDF主体中声明变量 上下文:我试图构建一个函数,将标题大小写应用于字符串 我试过: CREATE CREATE OR REPLACE FUNCTION mydataset.title_case(word STRING) as ( DECLARE i INT64; SET i = ARRAY_LENGTH(SPLIT(word, " &q

我试图在BigQuery上创建一个带有while循环的UDF函数,但我在文档中没有看到任何语法指南,这些指南专门针对这种情况,也没有在UDF主体中声明变量

上下文:我试图构建一个函数,将标题大小写应用于字符串

我试过:

CREATE CREATE OR REPLACE FUNCTION mydataset.title_case(word STRING) as (
    DECLARE i INT64;
    SET i = ARRAY_LENGTH(SPLIT(word, " "));
    ...
);

但是,它不喜欢UDF主体中的DECLARE或SET。正确的语法是什么?

关于如何在UDF中使用和设置变量的问题,您必须在代码开头声明和设置变量。然后,将其作为参数传递给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...
);
上下文:我试图构建一个函数,将标题大小写应用于字符串

与其直接回答这个问题,我倒不如谈谈我认为促使这个问题首先被提出的原因

从我在这里的经验来看,这是显而易见的,所以老年退休金计划经常问一些问题,这些问题实际上是为了帮助他们走错方向!在许多情况下,这是一种悲伤的经历,因为你知道你并没有对这样的人提供很好的帮助,而恰恰相反。我为自己多次参与其中而感到内疚,因为它并不总是真正清楚什么是真正的用例,所以并没有太多的选项可以帮助我,而不是像被问到的那个样回答确切的问题

我认为在这种情况下——上面的问题很好地暗示了真正的目的/用例——所以正如我已经说过的,我想回答它(用例)

在大多数情况下,您实际上不需要执行循环-您应该尝试以基于sql的方式实现这一点

因此,提示在下面的语句中

上下文:我试图构建一个函数,将标题大小写应用于字符串

处理title-case函数的简单方法如下

#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`
输出如下

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    

注意:以上只是一个(或两个)示例,说明了如何避免无效的基于光标的处理,而不是在SQL中执行“一体式”(基于集合的)转换。对这一点知道得很模糊,但还没来得及使用它。很高兴知道。因此,将变量声明放在函数之外,我担心调用函数时不会调用它们,以防函数是永久函数。我会试试看。实际上我改变了主意,选择了你的,因为它确实回答了实际问题。@Benjamin,你可以将UDf与SQL或JavaScript结合使用,这非常有用。我很高兴知道它有帮助。那太好了!我喜欢unnest在这里的用法,希望我曾经考虑过:)在第一个示例中,我没有得到的一点是使用| | inside string_agg()。第二个例子是,在我试着理解它之前,我需要再来一杯咖啡。谢谢
|
是一个串联运算符:o)-作为第二个示例-当然-休息一下,然后开始:o)好的,我现在知道了。我建议
选择IF(REGEXP_包含(LAG(char)OVER(ORDER BY OFFSET)、r'\w')、LOWER(char)、UPPER(char))
添加
LOWER()
,以确保它也能纠正已经大写或混乱的字符串。我正在使用您的解决方案,但我选择了另一个答案,因为它直接回答了开头的问题(即变量)。不过,我更喜欢您的SQL方法。我很高兴您注意到在此处使用LOWER的细微差别。:o)
#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