PARSE_DATE : 解析函数 BigQuery/Standard SQL 的结果无效

Posted

技术标签:

【中文标题】PARSE_DATE : 解析函数 BigQuery/Standard SQL 的结果无效【英文标题】:PARSE_DATE : Invalid result from parsing function BigQuery/Standard SQL 【发布时间】:2019-02-05 12:16:32 【问题描述】:

我在 BigQuery(标准 SQL)中有以下代码:

SAFE_CAST (PARSE_DATE('%Y-%m-%d',JSON_EXTRACT_SCALAR(g.p_dataforanalytics,'$.birthday') ) as string)

由于以下原因导致失败:

解析函数的结果无效

问题是我无法控制我在g.p_dataforanalytics 中获得的数据,其中一些是纯垃圾,格式不正确,有时甚至不是合理的值。 有没有办法定义如果PARSE_DATE() 失败,它将返回 NULL 而不会抛出查询?

基本上我正在寻找任何编程语言中的 try/catch 之类的东西?

【问题讨论】:

【参考方案1】:

解析上使用SAFE.前缀:

SAFE.PARSE_DATE('%Y-%m-%d', JSON_EXTRACT_SCALAR(g.p_dataforanalytics, '$.birthday') )

我看不到将其转换回字符串的实用程序,除非您想要这样的解决方案:

COALESCE(FORMAT('%Y-%m-%d',
                COALESCE(SAFE.PARSE_DATE('%Y-%m-%d', JSON_EXTRACT_SCALAR(g.p_dataforanalytics, '$.birthday'), 
                         SAFE.PARSE_DATE('%m/%d/%Y', JSON_EXTRACT_SCALAR(g.p_dataforanalytics, '$.birthday')
                        ) 

                ), JSON_EXTRACT_SCALAR(g.p_dataforanalytics, '$.birthday'
        )

也就是说,如果代码测试了不同的日期格式,选择其中一种,将其转回 YYYY-MM-DD 格式。并且,如果所有格式都不起作用,则保留原始值。

【讨论】:

转换为字符串是因为我将其与更多字段合并为字符串,并且合并强制所有字段具有相同类型 @Luis 。 . .如果不将值用作日期,为什么需要先将其转换为日期? 要在 YYYY-MM-DD 中获取它,我知道也可以使用字符串操作,但这似乎需要更多编码【参考方案2】:

以下是 BigQuery 标准 SQL 和(我认为)通过使用 moment.js 库和 BigQuery UDF 和外部库来涵盖大多数疯狂的日期表示变化。

注意:你需要将moment.js上传到GCS上的your_bucket

#standardSQL
CREATE TEMPORARY FUNCTION PARSE_DATE_CUSTOM(format_string STRING, date_string STRING )
RETURNS STRING
LANGUAGE js AS """
        return moment(date_string).format(format_string);
"""
OPTIONS (
    library="gs://your_bucket/moment.js"
);
SELECT 
  JSON_EXTRACT_SCALAR(g.p_dataforanalytics, '$.birthday') birthday_in_json,
  PARSE_DATE_CUSTOM('YYYY-MM-DD', JSON_EXTRACT_SCALAR(g.p_dataforanalytics, '$.birthday')) birthday
FROM `project.dataset.table` g

如您所见 - 这里引入了一个新的自定义函数 PARSE_DATE_CUSTOM(format_string STRING, date_string STRING ) - 它接受表示您希望最终输出的日期和格式的任何字符串。支持的格式是 here

您可以使用虚拟数据进行测试,使用上面的简化示例,如下面的简化示例

#standardSQL
CREATE TEMPORARY FUNCTION PARSE_DATE_CUSTOM(format_string STRING, date_string STRING )
RETURNS STRING
LANGUAGE js AS """
        return moment(date_string).format(format_string);
"""
OPTIONS (
    library="gs://your_bucket/moment.js"
);
WITH `project.dataset.table` AS (
  SELECT '"birthday":"2000-12-31"' p_dataforanalytics UNION ALL
  SELECT '"birthday":"2000-15-31"' UNION ALL
  SELECT '"birthday":"12/31/2000"' UNION ALL
  SELECT '"birthday":"31 Dec 2000"' UNION ALL
  SELECT '"birthday":"Around 2000, Dec 31"' 
)
SELECT 
  JSON_EXTRACT_SCALAR(g.p_dataforanalytics, '$.birthday') birthday_in_json,
  PARSE_DATE_CUSTOM('YYYY-MM-DD', JSON_EXTRACT_SCALAR(g.p_dataforanalytics, '$.birthday')) birthday
FROM `project.dataset.table` g

结果

Row     birthday_in_json        birthday     
1       2000-12-31              2000-12-31   
2       2000-15-31              Invalid date     
3       12/31/2000              2000-12-31   
4       31 Dec 2000             2000-12-31   
5       Around 2000, Dec 31     2000-12-31   

【讨论】:

以上是关于PARSE_DATE : 解析函数 BigQuery/Standard SQL 的结果无效的主要内容,如果未能解决你的问题,请参考以下文章

带有多索引和 parse_date 的 pandas read_excel;如何?

标准 SQL (BigQuery) 中整数 YYYYMMDD 的日期

将一年中的一天和一年中的日期转换为大查询

BigQuery AEAD 功能的密钥集管理最佳实践 [关闭]

大查询 - 将INT转换为日期

12306购票测试运行以及完整代码