【问题标题】:compute sum of values associated with overlapping date ranges计算与重叠日期范围相关的值的总和
【发布时间】:2014-03-06 18:21:42
【问题描述】:

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

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 条记录,我很确定答案涉及使用窗口函数,但我完全不知所措......

有没有办法做到这一点?

提前非常感谢!

【问题讨论】:

    标签: postgresql date-range


    【解决方案1】:

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

    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
    

    演示:http://sqlfiddle.com/#!15/ef6cb/13

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


    编辑
    最里面的查询中的order by 子句是多余的,可以跳过,因为lead(x) over caluse 按日期对记录进行排序,并且不需要对来自最里面的子查询的结果集进行排序。

    【讨论】:

    • 这是一个很棒的解决方案,谢谢(实际上,我最诚挚的感谢(!),我今晚可以睡觉了......)。我很想知道是否有任何其他方法/技术可以用来达到相同的效果。
    猜你喜欢
    • 1970-01-01
    • 2020-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多