Postgresql 计算与重叠日期范围关联的值之和

Postgresql 计算与重叠日期范围关联的值之和,postgresql,date-range,Postgresql,Date Range,我有一个简单的日期范围表,每个表都有相关的每周小时数: CREATE TABLE tmp_ranges ( id SERIAL PRIMARY KEY, rng daterange, hrs_per_week INT ); 以及一些我想计算(即合计)重叠/交叉日期范围每周小时数总和的值: INSERT INTO tmp_ranges (rng, hrs_per_week) VALUES ('[2014-03-15, 2014-06-28]', 9), ('[2014-

我有一个简单的日期范围表,每个表都有相关的每周小时数:

CREATE TABLE tmp_ranges (
  id SERIAL PRIMARY KEY,
  rng daterange,
  hrs_per_week INT
 );
以及一些我想计算(即合计)重叠/交叉日期范围每周小时数总和的值:

INSERT INTO tmp_ranges (rng, hrs_per_week) VALUES
   ('[2014-03-15, 2014-06-28]', 9),
   ('[2014-04-18, 2014-07-15]', 2),
   ('[2014-06-03, 2014-09-12]', 9),
   ('[2014-10-03, 2014-11-14]', 6);
从图形上看(希望这能揭示更多信息,而不是掩盖更多信息),解决方案如下所示:

hrs/wk      T                                                 T`
  9         |  }-----|--------|-------->                      |
            |                                                 |
  2         |        }--------|--------|----->                |
            |                                                 |
  9         |                 }--------|------|---->          |
            |                                                 |
  6         |                                          }--->  |
            |                                                 |
 agg.hrs/wk     --9-- ---11--- ---20--- --11-- --9--    -6- 
最终日期范围故意与其他记录不连续,但仍将包含在最终记录集中…
很明显,这个解决方案需要从原来的4条记录中生成6条记录,我很确定答案涉及到使用窗口函数,但我完全不知所措

有没有办法做到这一点


非常感谢

以下是我解决这个问题的尝试:

select y,
     sum( hrs_per_week )
from tmp_ranges t
join(
  select daterange( x,
         lead(x) over (order by x) ) As y
  from (
    select lower( rng ) As x
    from tmp_ranges
    union 
    select upper( rng )
    from tmp_ranges
    order by x
  ) y
) y
on t.rng && y.y
group by y
order by y
演示:

最里面的子查询使用
union
将所有边界日期收集到一个集合中,然后对它们进行排序。
然后,外部子查询使用
lead
函数从相邻日期构建新范围。
最后,这些新范围被加入到主查询中的源表中,进行聚合,并计算
sum


编辑

最里面的查询中的
orderby
子句是多余的,可以跳过,因为
lead(x)over
caluse orders按日期记录,最里面的子查询的结果集不必排序。

这是一个非常好的解决方案,谢谢你(实际上,我最真诚的感谢(!),我今晚可以睡觉了……)。我很想知道是否还有其他方法/技术可以达到同样的效果。