如何根据 Presto 中的日期间隔取消嵌套 table?

How to unnest the table based on date interval in Presto?

我有一个 table 事件,其中 start_dt 是事件的开始,end_dt 是事件的结束。此 table 由从 end_dt 派生的 dt 列分区。这意味着在午夜之前开始和在午夜之后结束的事件只存在于一个分区中。我需要做的是将每个事件分成与事件关联的日期数一样多的行。有什么聪明的方法可以使用 Presto SQL 语法来实现它?

输入:

  id  | start_dt                 | end_dt                  | dt
------+--------------------------+-------------------------+----------
 1    | 2020-09-24 21:56:12.669  | 2020-09-25 00:26:16.440 | 2020-09-25
 2    | 2020-09-25 17:12:02.699  | 2020-09-25 17:42:02.699 | 2020-09-25
 3    | 2020-09-23 23:47:29.146  | 2020-09-25 00:17:29.146 | 2020-09-25

预期输出:

  id  | start_dt                 | end_dt                  | dt
------+--------------------------+-------------------------+----------
 1    | 2020-09-24 21:56:12.669  | 2020-09-24 23:59:59.999 | 2020-09-24
 1    | 2020-09-25 00:00:00.001  | 2020-09-25 00:26:16.440 | 2020-09-25
 2    | 2020-09-25 17:12:02.699  | 2020-09-25 17:42:02.699 | 2020-09-25
 3    | 2020-09-23 23:47:29.146  | 2020-09-23 23:59:59.999 | 2020-09-23
 3    | 2020-09-24 00:00:00.001  | 2020-09-24 23:59:59.999 | 2020-09-24
 3    | 2020-09-25 00:00:00.001  | 2020-09-25 00:17:29.146 | 2020-09-25

在 Presto 中,您可以使用 sequence() 生成日期数组。剩下的只是取消嵌套和条件逻辑:

select t.id, 
    case when date(t.start_dt) = s.dt then t.start_dt else cast(s.dt as timestamp)                    end as new_start_dt,
    case when date(t.end_dt)   = s.dt then t.end_dt   else cast(s.dt as timestamp) + interval '1' day end as new_end_dt,
    s.dt
from mytable t
cross join unnest(sequence(date(t.start_dt), date(t.end_dt))) as s(dt)

请注意,这会生成恰好在午夜开始和结束的日期间隔:half-open 间隔逻辑对我来说比在这里或那里删除或添加毫秒更有意义。如果您愿意,可以轻松更改它。