JS UDF 返回标准 SQL/BigQuery 的结构并创建两列

3 javascript sql database google-bigquery

I\xe2\x80\x99m 尝试使用 Javascript 为 BigQuery 编写一个用户定义的函数,该函数返回一个结构并生成两列:

\n\n
CREATE TEMP FUNCTION exampleFunction(exampleString STRING)\n  RETURNS STRUCT<index INT64, latency INT64> LANGUAGE js AS\n  LANGUAGE js AS \n"""\n    var exampleStruct = {1:100, 2:200}\n    return exampleStruct;\n""";\n
Run Code Online (Sandbox Code Playgroud)\n\n

我的查询是这样的:

\n\n
SELECT\nexampleCol,\nexampleFunction(stringCol) -- use SELECT AS STRUCT somewhere here? with the aliases \xe2\x80\x9cFirst\xe2\x80\x9d and \xe2\x80\x9cSecond\xe2\x80\x9d\nFROM\n[SOME DATATBASE HERE]\n
Run Code Online (Sandbox Code Playgroud)\n\n

我希望 的exampleFunction(stringCol)输出生成两列(如果我们包含 则总共三列exampleCol)。例如,如果exampleCol给我们\xe2\x80\x9cSOMETHING\xe2\x80\x9d,我\xe2\x80\x99d想要返回列:\xe2\x80\x9cSOMETHING\xe2\x80\x9d for exampleCol,1 for \ xe2\x80\x9cFirst\xe2\x80\x9d,2 表示 \xe2\x80\x9cSecond\xe2\x80\x9d。这有可能吗?

\n\n

我\xe2\x80\x99m 无法从 JS 函数返回 STRUCT(不确定我的语法是否关闭)并无法正确获取查询。对于查询,我想避免运行 JavaScript 函数两次。谢谢!

\n

小智 5

我想补充 Mikhail Berlyant 的答案,在这种情况下效果很好,但我在稍微不同的情况下遇到了问题。

我建议使用一个新对象来完成此操作,而不是在 JavaScript 中使用“this”来保留跨行的数据。

在我的示例中,我想再返回一列,该列值基于另一个现有列的值。我将再添加一列名为“latencyUnder150”的列,如果延迟字段的值低于 150,则该列的值为“Y”,否则将该字段留空。

#standardSQL
CREATE TEMP FUNCTION exampleFunction(exampleString STRING)
  RETURNS STRUCT<index INT64, latency INT64, latencyUnder150 STRING> 
  LANGUAGE js AS 
"""
    arr = exampleString.split(':');
    this.index = arr[0];
    this.latency = arr[1];
    if (this.latency < 150) {
        this.latencyUnder150 = 'Y'
    }
    return this;
""";
WITH `project.dataset.table` AS (
  SELECT 1 exampleCol, '10:100' stringCol UNION ALL
  SELECT 2, '20:200' UNION ALL
  SELECT 3, '30:456'
)
SELECT exampleCol, exampleFunction(stringCol).*
FROM `project.dataset.table`
-- ORDER BY exampleCol   
Run Code Online (Sandbox Code Playgroud)

在 JS 中使用“this”变量,你会得到这个答案。

| Row | exampleCol | index | latency | latencyUnder150 |
|-----|------------|-------|---------|-----------------|
| 1   | 1          | 10    | 100     | Y               |
| 2   | 2          | 20    | 200     | Y               |
| 3   | 3          | 30    | 456     | Y               |
Run Code Online (Sandbox Code Playgroud)

您可以看到字段 LatencyUnder150 保留第一条记录中的值“Y”。

通过稍微更改代码以使用新对象,每一行开始时都没有前一行的值。

#standardSQL
CREATE TEMP FUNCTION exampleFunction(exampleString STRING)
  RETURNS STRUCT<index INT64, latency INT64, latencyUnder150 STRING> 
  LANGUAGE js AS 
"""
    var outObj = {}
    arr = exampleString.split(':');
    outObj.index = arr[0];
    outObj.latency = arr[1];
    if (outObj.latency < 150) {
        outObj.latencyUnder150 = 'Y'
    }
    return outObj;
""";
WITH `project.dataset.table` AS (
  SELECT 1 exampleCol, '10:100' stringCol UNION ALL
  SELECT 2, '20:200' UNION ALL
  SELECT 3, '30:456'
)
SELECT exampleCol, exampleFunction(stringCol).*
FROM `project.dataset.table`
-- ORDER BY exampleCol   
Run Code Online (Sandbox Code Playgroud)
| Row | exampleCol | index | latency | latencyUnder150 |
|-----|------------|-------|---------|-----------------|
| 1   | 1          | 10    | 100     | Y               |
| 2   | 2          | 20    | 200     | (null)          |
| 3   | 3          | 30    | 456     | (null)          |
Run Code Online (Sandbox Code Playgroud)