簡體   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