【问题标题】:Encapsulating complex code in BigQuery在 BigQuery 中封装复杂代码
【发布时间】:2018-08-13 15:15:27
【问题描述】:

我最近不得不从其他 BQ 表中生成一个 BQ 表。逻辑相当复杂,我最终编写了一个复杂的 SQL 语句。

在 Oracle SQL 中,我会编写一个 PL/SQL 过程,其中将逻辑分解为单独的部分(最常见的是合并语句)。在某些情况下,我会将一些代码封装到函数中。生成的过程将是一系列 DML 语句,易于阅读和维护。

但是 BQ 没有类似的东西。 UDF 只是临时的,不能存储在一个视图中。

问题:我正在寻找使复杂的 BQ SQL 代码更模块化和更易读的方法。有什么办法可以做到吗?

【问题讨论】:

    标签: google-bigquery user-defined-functions


    【解决方案1】:

    当前可用的选项是使用WITH Clause

    WITH 子句包含一个或多个命名子查询,其输出充当临时表,后续 SELECT 语句可以在任何子句或子查询中引用该临时表

    我仍然认为User-Defined Functions 是一个非常好的选择。
    JS 和 SQL UDF 可在 BigQuery 中使用,众所周知,BigQuery 团队正在努力引入 permanent UDF 即将推出

    与此同时,您可以将 JS UDF 的主体存储为 js 库,并使用 OPTIONS 部分在您的 UDF 中引用它。请参阅上述参考中的Including external libraries

    2019 年 10 月更新

    使用scriptingstored procedures 的功能现在处于测试阶段。

    因此,您可以在一个请求中向 BigQuery 发送多个语句、使用变量以及使用 IF 和 WHILE 等控制流语句等。
    而且,您可以使用过程,它是可以从其他查询中调用的语句块。

    注意:它还处于测试阶段

    【讨论】:

    • 感谢您的回复。我想避免使用 js,因为我还不熟悉它,但我会调查。
    • 当然。所以我认为 WITH 和 SQL UDF 是适合你的方法:o)
    【解决方案2】:

    BigQuery 支持持久的用户定义函数。要开始使用,请参阅the documentation

    例如,这是一个 CREATE FUNCTION 语句,它创建了一个函数来计算数组的中位数:

    CREATE FUNCTION dataset.median(arr ANY TYPE) AS (
      (
        SELECT
          IF(
            MOD(ARRAY_LENGTH(arr), 2) = 0,
            (arr[OFFSET(DIV(ARRAY_LENGTH(arr), 2) - 1)] + arr[OFFSET(DIV(ARRAY_LENGTH(arr), 2))]) / 2,
            arr[OFFSET(DIV(ARRAY_LENGTH(arr), 2))]
          )
        FROM (SELECT ARRAY_AGG(x ORDER BY x) AS arr FROM UNNEST(arr) AS x)
      )
    );
    

    执行此语句后,可以在后续查询中引用:

    SELECT dataset.median([7, 1, 2, 10]) AS median;
    

    您还可以在逻辑视图中引用该函数。请注意,您目前需要使用项目来限定对视图内函数的引用,但是:

    CREATE VIEW dataset.sampleview AS
    SELECT x, `project-name`.dataset.median(array_column) AS median
    FROM `project-name`.dataset.table
    

    【讨论】:

    • 无论如何,我宁愿将此作为评论或对现有答案的更新添加:o) - BigQuery 团队干得好!谢谢!!!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-04
    • 2018-07-16
    • 1970-01-01
    • 1970-01-01
    • 2016-07-23
    • 2018-04-05
    • 2017-10-17
    相关资源
    最近更新 更多