[英]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.