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

时间:2019-02-05 12:16:32

标签: sql google-bigquery

我在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之类的东西吗?

2 个答案:

答案 0 :(得分:1)

parse 上使用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格式。而且,如果没有一种格式有效,则保留原始值。

答案 1 :(得分:0)

以下内容适用于BigQuery Standard 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