【问题标题】:Cast DATETIME to STRING working on ARRAY of STRUCT on BigQuery Standard SQL将 DATETIME 转换为 STRING,在 BigQuery 标准 SQL 中处理 STRUCT 的 ARRAY
【发布时间】:2018-08-27 05:23:08
【问题描述】:

在我的表中,我有一个名为“消息”的属性,它具有这种确切的数据类型:

ARRAY<STRUCT<created_time  DATETIME ,`from` STRUCT<id STRING, 
name STRING,email STRING>, id STRING, message STRING>>

我已经定义了一个名为 my_func() 的 UDF

因为 Big Query 中的 UDF 函数不支持类型 DATETIME,所以我需要转换属性 created_time。

所以我尝试了这个:

safe_cast ( messages as ARRAY<STRUCT<created_time  STRING ,
'from` STRUCT<id STRING, name STRING, email STRING>,
id STRING, message STRING>>) as messages_casted 

我得到了这个错误

Casting between arrays with incompatible element types is not
supported: Invalid cast from...

我转换数组结构的方式有错误?

有一些方法可以将 UDF 与这种数据结构一起使用,还是唯一的方法是展平数组并进行强制转换?

我的目标是在JS执行环境中获取数组,以便与JS代码进行聚合。

【问题讨论】:

    标签: sql datetime google-cloud-platform google-bigquery user-defined-functions


    【解决方案1】:

    使用 JavaScript UDF 时,您无需显式指定复杂的输入数据类型。相反,您可以使用TO_JSON_STRING function。在您的情况下,您可以让 UDF 将 messages 作为 STRING,然后在 UDF 中对其进行解析。例如,您可以致电my_func(TO_JSON_STRING(messages))

    这是一个例子from the documentation

    CREATE TEMP FUNCTION SumFieldsNamedFoo(json_row STRING)
      RETURNS FLOAT64
      LANGUAGE js AS """
    function SumFoo(obj) {
      var sum = 0;
      for (var field in obj) {
        if (obj.hasOwnProperty(field) && obj[field] != null) {
          if (typeof obj[field] == "object") {
            sum += SumFoo(obj[field]);
          } else if (field == "foo") {
            sum += obj[field];
          }
        }
      }
      return sum;
    }
    var row = JSON.parse(json_row);
    return SumFoo(row);
    """;
    
    WITH Input AS (
      SELECT STRUCT(1 AS foo, 2 AS bar, STRUCT('foo' AS x, 3.14 AS foo) AS baz) AS s, 10 AS foo UNION ALL
      SELECT NULL, 4 AS foo UNION ALL
      SELECT STRUCT(NULL, 2 AS bar, STRUCT('fizz' AS x, 1.59 AS foo) AS baz) AS s, NULL AS foo
    )
    SELECT
      TO_JSON_STRING(t) AS json_row,
      SumFieldsNamedFoo(TO_JSON_STRING(t)) AS foo_sum
    FROM Input AS t;
    +---------------------------------------------------------------------+---------+
    | json_row                                                            | foo_sum |
    +---------------------------------------------------------------------+---------+
    | {"s":{"foo":1,"bar":2,"baz":{"x":"foo","foo":3.14}},"foo":10}       | 14.14   |
    | {"s":null,"foo":4}                                                  | 4       |
    | {"s":{"foo":null,"bar":2,"baz":{"x":"fizz","foo":1.59}},"foo":null} | 1.59    |
    +---------------------------------------------------------------------+---------+
    

    【讨论】:

    • 感谢两者,但我认为使用 TO_JSON_STRING 的解决方案是解决所有问题的方法!
    【解决方案2】:

    因为 Big Query 中的 UDF 函数不支持类型 DATETIME,所以我需要转换属性 created_time。

    以下适用于 BigQuery 标准 SQL,是一种非常简单的转换 ARRAY 的特定元素的方法,其他所有内容保持不变。
    所以在下面的例子中 - 它 CASTs created_time 从 DATETIMESTRING (你可以使用你需要的任何兼容类型)

    #standardSQL
    SELECT messages,
      ARRAY(SELECT AS STRUCT * REPLACE (SAFE_CAST(created_time AS STRING) AS created_time) 
        FROM UNNEST(messages) message
      ) casted_messages
    FROM `project.dataset.table`  
    

    如果您针对您的数据运行它 - 您将看到原始消息和转换消息 - 所有元素应该相同(值/类型),但(如预期的那样) created_time 将是转换类型(在这种特殊情况下为字符串)如果不兼容,则为 NULL

    您可以使用下面的虚拟数据测试/玩上面的内容

    #standardSQL
    WITH `project.dataset.table` AS (
      SELECT [STRUCT<created_time  DATETIME, 
                `from` STRUCT<id STRING, name STRING, email STRING>, 
                id STRING, 
                message STRING>
          (DATETIME '2018-01-01 13:00:00', ('1', 'mike', 'zzz@ccc'), 'a', 'abc'),
          (DATETIME '2018-01-02 14:00:00', ('2', 'john', 'yyy@bbb'), 'b', 'xyz')
        ] messages
    )
    SELECT messages,
      ARRAY(SELECT AS STRUCT * REPLACE (SAFE_CAST(created_time AS STRING) AS created_time) 
        FROM UNNEST(messages) message
      ) casted_messages
    FROM `project.dataset.table`
    

    【讨论】:

      猜你喜欢
      • 2019-03-30
      • 2019-03-22
      • 2022-12-17
      • 2020-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多