如何计算雪花中的日期差异?

Posted

技术标签:

【中文标题】如何计算雪花中的日期差异?【英文标题】:How to calculate difference in date in snowflake? 【发布时间】:2021-10-26 21:13:37 【问题描述】:

我有这两天:

BEFORE_DATETIME: 2021-09-02 09:41:00
AFTER_DATETIME: 2021-09-09 09:41:00

我需要计算这两天的差异。所以在这个例子中:7 天。但是,在 BEFORE_DATETIME,我有一些字符串值(坏记录)。由于这些记录,我在使用 DATEDIFF 函数时不断收到错误消息。

如何计算日期差异并忽略不良记录?

【问题讨论】:

【参考方案1】:

您可以使用TRY_TO_TIMESTAMP 函数将您的输入解析为时间戳,如果解析失败则返回NULL

那么您可以随意申请您的DATEDIFF

WITH cte AS (
  SELECT
     $1 AS before_datetime,
     $2 AS after_datetime
  FROM VALUES
  ('2021-09-02 09:41:00', '2021-09-09 09:41:00'),
  ('random_bad_record', '2021-09-09 09:41:00'),
  ('2021-09-02 09:41:00', 'random_bad_record')
)
SELECT
    TRY_TO_TIMESTAMP(before_datetime) as before_datetime,
    TRY_TO_TIMESTAMP(after_datetime) as after_datetime,
    DATEDIFF('days', TRY_TO_TIMESTAMP(before_datetime), TRY_TO_TIMESTAMP(after_datetime)) AS diff_in_days
FROM cte
;

【讨论】:

您好,非常感谢!我认为这可行,但我有两列值(数千条记录),我需要在“FROM VALUES”下输入每一列吗? 当然不是,FROM VALUE 只是为了在单个可读查询中重现您的用例。从您的角度来看,您只需要使用最终查询。我对其进行了更新,以便在最终查询中使用 TRY_TO_TIMESTAMP 并使其更适合您。 道歉,你是对的!有效,非常感谢!非常感谢您的帮助!【参考方案2】:

如果您使用TRY_TO_DATE 并且值“解析失败”,您将得到空值, 因此,您可以将该 TRY 的结果输入 DATEDIFF,或者您可以使用您跳过的内联 IFF,例如:

IFF(TRY_TO_DATE(before_datetime) IS NOT NULL AND TRY_TO_DATE(after_datetime) IS NOT NULL, 
    DATEDIFF('days', before_datetime, after_datetime),
    0) AS alias_name

当值不好时用你想要的替换0。等等

【讨论】:

【参考方案3】:

我想补充一下关于这一点的讨论:

我有一些字符串值(坏记录)。

我看到不一致的日期/时间数据 - 从各种来源提取或由人以不同格式输入。如果你有这样的“坏”日期,这个 SQL UDF 就派上用场了。在最终尝试基本的 TRY_TO_TIMESTAMP 之前,它将尝试各种常见的日期和时间格式。如果它们都不起作用,它将返回 NULL。

如果字符串字段中的日期格式不一致,则它更有可能转换日期,但应该在这种情况下使用,因为它会增加转换的开销。您可以查看该模式的工作原理,并将您自己的解析器添加到尝试列表中。

create or replace function TRY_MULTI_TIMESTAMP(STR string)
returns timestamp
language SQL
as
$$
    case
        when STR RLIKE '[A-Za-z]3 \\d2 \\d4 \\d1,2:\\d2:\\d2' then try_to_timestamp(left(STR, 20), 'MON DD YYYY HH24:MI:SS')
        when STR RLIKE '\\d1,4-\\d1,2-\\d2 \\d1,2:\\d2:\\d2 [A|P][M]' then try_to_timestamp(STR, 'YYYY-MM-DD HH12:MI:SS AM')
        when STR RLIKE '\\d1,2/\\d1,2/\\d4' then try_to_timestamp(STR, 'mm/dd/yyyy')
        when STR RLIKE '\\d1,2\\/\\d1,2\\/\\d4 \\d1,2:\\d2:\\d2 [A-Za-z]2' then try_to_timestamp(STR, 'MM/DD/YYYY HH12:MI:SS AM')
        when STR RLIKE '\\d1,2\\/\\d1,2\\/\\d4 \\d1,2:\\d2' then try_to_timestamp(STR, 'MM/DD/YYYY HH24:MI')
        when STR RLIKE '[A-Za-z]3, \\d1,2 [A-Za-z]3 \\d4 \\d1,2:\\d1,2:\\d1,2 [A-Za-z]3' then try_to_timestamp(left(STR, len(STR) - 4) || ' ' || '00:00', 'DY, DD MON YYYY HH:MI:SS TZH:TZM')   -- From Snowflake "LIST" command
        when STR RLIKE '\\d1,2/\\d1,2/\\d2 \\d1,2:\\d2 [A|P][M]' then try_to_timestamp(STR, 'MM/DD/YY HH12:MI AM')
        when STR RLIKE '[A-Za-z]3 [A-Za-z]3 \\d2 \\d4 \\d1,2:\\d2:\\d2 GMT.*' then try_to_timestamp(left(replace(substr(STR, 5), 'GMT', ''), 26), 'MON DD YYYY HH:MI:SS TZHTZM')  -- javascript
        else try_to_timestamp(STR) -- Final try without format specifier.
    end
$$;

select try_multi_timestamp('Sat Oct 02 2021 17:53:40 GMT+0000 (Coordinated Universal Time)'); -- JavaScript date format
select try_multi_timestamp('Fri, 17 Apr 2020 17:55:45 GMT'); -- Snowflake LIST command file time
select try_multi_timestamp('Oct 26 2021 6:25:15');

【讨论】:

以上是关于如何计算雪花中的日期差异?的主要内容,如果未能解决你的问题,请参考以下文章

计算Java中的日期差异

如何将长口头日期时间转换为雪花中的时间戳(YYYY-MM-DD HH:MM:SS)?

从Oracle中的日期差异计算年份

计算特定年份的sql中的日期差异

使用数据帧中的某些参数计算日期之间的差异

如何在雪花中将时间戳转换为日期