从具有开始和结束日期的记录列表中获取每个工作日的平均持续时间

Get average duration per week-day from a list of records with start and end date

我有一个包含三列的输入 table :

我想获得每 周-天 条记录的平均持续时间(end_date - start_date)。

我的问题是:如果我有一个记录,其中 start_date 和 end_date 之间的间隔是 4 天,我想每天获取结果,而不仅仅是在 start_dateend_date,例如,如果我在 3 周之间没有记录,则将工作日的任何值作为平均值的 'zero' 值。

示例:

id start_date end_date
1 (Friday to Sunday) 2021-03-12T01:00:00.000Z 2021-03-14T01:00:00.000Z
2 (Friday) 2021-03-12T01:00:00.000Z 2021-03-12T05:00:00.000Z
3 (Wed.) 2021-03-03T16:00:00.000Z 2021-03-03T17:00:00.000Z

预期结果(这里以欧洲工作日为例,周日是7):

weekday avg_duration_seconds
1 0
2 0
3 1800
4 0
5 48600
6 86400
7 3600

感谢您的帮助!

注意:以下内容也适用于您标记的 Postgres。我不知道这是否也适用于 CockroachDB。

您可以使用 generate_series() 将 start/end 时间戳“扩展”到几天。要计算每一天的有效持续时间,需要在开始和结束时将全天与部分天区别对待。一旦计算出这些时间戳,就很容易获得每天的持续时间。在所有工作日进行左连接并按它们分组:

select x.weekday, 
       avg(extract(epoch from real_end - real_start)) as duration
from generate_series(1,7) as x(weekday) 
left join (      
    select t.id, 
           extract(isodow from g.dt) as weekday,
           case  
             when start_date < g.dt then date_trunc('day', g.dt)
             else start_date
           end as real_start, 
           case 
             when end_date::date > g.dt then date_trunc('day', g.dt::date + 1)
             else end_date
           end as real_end
    from the_table t
      cross join generate_series(start_date, end_date, interval '1 day') as g(dt)
  ) t on x.weekday = t.weekday
group by x.weekday  
order by x.weekday;  

我对“real_start”和“real_end”的表达并非 100% 涵盖所有极端情况,但它应该足以让您入门。

结果与您的预期略有不同,因为 2021-03-02 和 2021-03-11 的工作日有误。

Online example