BigQuery:验证所有日期的格式为 yyyy-mm-dd

Posted

技术标签:

【中文标题】BigQuery:验证所有日期的格式为 yyyy-mm-dd【英文标题】:BigQuery: Validate that all dates are formatted as yyyy-mm-dd 【发布时间】:2019-05-10 13:35:02 【问题描述】:

使用 Google BIGQUERY,我需要检查名为birth_day_col 的列中的值是否是正确且所需的日期格式:YYYY-MM-DD。此列中的值定义为 STRING。此外,此列中的值目前采用以下格式:YYYY-MM-DD。

我在互联网上进行了大量研究,发现了一个有趣的解决方法。以下查询:

SELECT
    DISTINCT birth_day_col
    FROM `project.dataset.datatable`
    WHERE birth_day_col LIKE '[1-2][0-9][0-9][0-9]/[0-1][0-9]/[0-3][0-9]'
    AND country_code = 'country1'

但结果是:“此查询未返回任何结果。”

然后我使用以下代码检查了 NOT:

SELECT
    DISTINCT birth_day_col
    FROM `project.dataset.datatable`
    WHERE NOT(birth_day_col LIKE '[1-2][0-9][0-9][0-9]/[0-1][0-9]/[0-3][0-9]')
    AND country_code = 'country1'

令人惊讶的是,它给出了birth_dat_col 中的所有值,我已经验证并且日期格式正确,但这个结果很可能是巧合。

很奇怪(错误),我使用的查询应该只导致错误的日期格式,但它实际上给了我正确的日期。这两个查询的所有内容似乎都在颠倒每个人的角色。

对此业务案例的任何查询的预期结果是计算所有格式不正确的日期(即使当前为 0)。

感谢您的帮助!

罗伯特

【问题讨论】:

您的查询使用正斜杠 / 而不是破折号 - 作为日期组件分隔符。 ISO 8601 使用破折号,而不是斜线。 感谢您的反馈。我没有提到它。认为这无关紧要。我已经尝试使用- instad of /,但我得到了相同的结果。使用 . 而不是 / 时相同。 你试过用REGEX_CONTAINS代替LIKE吗? 当我使用NOT 函数时,它看起来几乎完全绕过了LIKE 函数,而是执行标准SELECT,只检查WHERE country_code = 'country1' 【参考方案1】:

这里有几件事:

    如果您想了解如何使用它,请阅读the LIKE operator 的文档。您似乎正在尝试使用正则表达式语法,但 LIKE 运算符不将正则表达式作为输入。 BigQuery 日期的标准格式是 YYYY-MM-DD,因此您可以尝试强制转换并查看结果是否为有效日期,例如:
SELECT SAFE_CAST(birth_day_col AS DATE) AS birth_day_col
FROM `project`.dataset.table

这将为任何格式不正确的值返回 null。如果你想找到所有格式不正确的,你可以在过滤器中使用SAFE_CAST

SELECT DISTINCT birth_day_col AS invalid_date
FROM `project`.dataset.table
WHERE SAFE_CAST(birth_day_col AS DATE) IS NULL

此查询的结果将是所有不使用 YYYY-MM-DD 格式的日期字符串。如果你想检查斜线,你可以使用REGEXP_CONTAINS,例如试试这个:

SELECT
  date,
  REGEXP_CONTAINS(date, r'^[0-9]4/[0-9]2/[0-9]2$')
FROM (
  SELECT '2019/05/10' AS date UNION ALL
  SELECT '2019-05-10' UNION ALL
  SELECT '05/10/2019'
)

如果您想查找 YYYY-MM-DD 格式或 YYYY/MM/DD 格式的所有日期,您可以使用如下查询:

SELECT
  DISTINCT date
FROM `project`.dataset.table
WHERE REGEXP_CONTAINS(date, r'^[0-9]4[/\-][0-9]2[/\-][0-9]2$')

例如:

SELECT
  DISTINCT date
FROM (
  SELECT '2019/05/10' AS date UNION ALL
  SELECT '2019-05-10' UNION ALL
  SELECT '05/10/2019'
)
WHERE REGEXP_CONTAINS(date, r'^[0-9]4[/\-][0-9]2[/\-][0-9]2$')

【讨论】:

是的,我在网上找到了 SAFE_CAST 的参考资料。我只是不明白使用它是否会给我 100% 正确的结果。 SAFE_CAST ... AS DATE 是否也会检查日期是否正确?例如,正如@Dai 下面所说:如果你有 2019/02/30 怎么办?如果这也检查这个会很有趣。请指教。谢谢! :) CASTSAFE_CAST 要求字符串的格式为 YYYY-MM-DD。它不能有斜线。我添加了另一个示例...目前还不清楚您想要做什么,但希望这很有用。【参考方案2】:

BigQuery Standrad SQL 的另一个示例 - 使用 SAFE.PARSE_DATE

#standardSQL
WITH `project.dataset.table` AS (
  SELECT '1980/08/10' AS birth_day_col UNION ALL
  SELECT '1980-08-10' UNION ALL
  SELECT '08/10/1980'
)
SELECT birth_day_col
FROM `project.dataset.table`
WHERE SAFE.PARSE_DATE('%Y-%m-%d', birth_day_col) IS NULL   

所有日期列表的结果不是格式为 yyyy-mm-dd

Row birth_day_col    
1   1980/08/10   
2   08/10/1980   

【讨论】:

【参考方案3】:

Google BigQuery's LIKE operator 不支持匹配数字,也不在其语法中使用 [ 字符(我认为 ISO 标准 SQL 也不支持 - LIKE 远没有 Regex 强大)。

X [NOT] LIKE Y

检查第一个操作数 X 中的 STRING 是否与第二个操作数 Y 指定的模式匹配。表达式可以包含以下字符:

百分号“%”匹配任意数量的字符或字节 下划线“_”匹配单个字符或字节 您可以使用两个反斜杠转义“\”、“_”或“%”。例如, ”\%”。如果您使用的是原始字符串,则只需要一个反斜杠。例如,r"\%"。

您应该改用REGEX_CONTAINS

我注意到,字符串格式测试不会告诉您日期是否有效。考虑2019-02-31 的日期格式有效,但日期值无效。我建议改用数据类型转换函数(将STRING 转换为DATE 值)。

【讨论】:

以上是关于BigQuery:验证所有日期的格式为 yyyy-mm-dd的主要内容,如果未能解决你的问题,请参考以下文章

将字符串转换为BIGQUERY中的日期当日期格式如下时:M / D / YYYY

BigQuery:将 mm/yyyy 日期与特定日期和 CURRENT_DATE 进行比较

如何将特定日期格式加载到 BigQuery

BigQuery 将字符串转换为日期

如何使用剑道验证器验证日期格式为 yyyy-MM-dd?

dd/mm/yyyy 格式的日期正则表达式,用于 javascript 验证