【问题标题】:PostgreSQL Price for multiple date ranges多个日期范围的 PostgreSQL 价格
【发布时间】:2011-05-05 11:42:48
【问题描述】:

我有给定日期范围内的下表。

我想编写一个 sql 查询 (PostgreSQL) 来获取给定期间的价格总和,如果它是一个连续的期间..例如:

如果我在第一组中指定 2011-05-02 到 2011-05-09,则应返回 6 行的总和,

但是

如果我在第二组中指定 2011-05-02 到 2011-05-011,则不应返回任何内容。

我的问题是我不知道如何确定日期范围是否是连续的……您能帮忙吗?非常感谢

案例 1:预期总和

 price       from_date      to_date
------    ------------  ------------
   1.0      "2011-05-02"  "2011-05-02"
   2.0      "2011-05-03"  "2011-05-03"
   3.0      "2011-05-04"  "2011-05-05"
   4.0      "2011-05-05"  "2011-05-06"
   5.0      "2011-05-06"  "2011-05-07"
   4.0      "2011-05-08"  "2011-05-09"

案例 2:没有预期结果

 price       from_date      to_date
------    ------------  ------------
   1.0      "2011-05-02"  "2011-05-02"
   2.0      "2011-05-03"  "2011-05-03"
   3.0      "2011-05-07"  "2011-05-09"
   4.0      "2011-05-09"  "2011-05-011"

我没有重叠的费率日期范围。

【问题讨论】:

  • 为什么第一个例子是连续的?价格5.0在2011-05-07结束,下一个两天后开始?
  • 如果在第一组中指定2011-05-022011-05-11 会怎样(假设(4.0 "2011-05-08" "2011-05-09") 之后没有行)?它应该返回与2011-05-022011-05-09 相同的结果吗?

标签: sql postgresql date-range continuous


【解决方案1】:

我不确定我是否完全理解了这个问题,但是这个呢:

select * 
from prices
where not exists (
  select 1 from (
     select from_date - lag(to_date) over (partition by null order by from_date asc) as days_diff
     from prices
     where from_date >= DATE '2011-05-01' 
       and to_date < DATE '2011-07-01'
  ) t 
  where coalesce(days_diff, 0) > 1
) 
order by from_date

【讨论】:

    【解决方案2】:

    这是一个相当古怪的解决方法:

    WITH RECURSIVE t AS (
      SELECT * FROM d WHERE '2011-05-02' BETWEEN start_date AND end_date 
      UNION ALL
      SELECT d.* FROM t JOIN d ON (d.key=t.key AND d.start_date=t.end_date+'1 DAY'::INTERVAL)  
         WHERE d.start_date <= '2011-05-09') 
      SELECT sum(price), min(start_date), max(end_date) 
      FROM t 
      HAVING min(start_date) <= '2011-05-02' AND max(end_date)>= '2011-05-09';
    

    【讨论】:

      【解决方案3】:

      我认为你需要结合窗口函数和 CTE:

      WITH
      raw_rows AS (
      SELECT your_table.*,
             lag(to_date) OVER w as prev_date,
             lead(from_date) OVER w as next_date
      FROM your_table
      WHERE ...
      WINDOW w as (ORDER by from_date, to_date)
      )
      SELECT sum(stuff)
      FROM raw_rows
      HAVING bool_and(prev_date >= from_date - interval '1 day' AND
                      next_date <= to_date + interval '1 day');
      

      http://www.postgresql.org/docs/9.0/static/tutorial-window.html

      http://www.postgresql.org/docs/9.0/static/queries-with.html

      【讨论】:

        猜你喜欢
        • 2016-06-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-26
        • 1970-01-01
        • 2020-10-22
        相关资源
        最近更新 更多