【问题标题】:Aggregate continuous ranges of dates聚合连续的日期范围
【发布时间】:2014-12-16 02:07:45
【问题描述】:

假设您有以下列出预订日期的 PostgreSQL 稀疏表:

CREATE TABLE reserved_dates (
    reserved_days_id    SERIAL  NOT NULL,
    reserved_date       DATE    NOT NULL
);

INSERT INTO reserved_dates (reserved_date) VALUES
    ('2014-10-11'),
    ('2014-10-12'),
    ('2014-10-13'),
    -- gap
    ('2014-10-15'),
    ('2014-10-16'),
    -- gap
    ('2014-10-18'),
    -- gap
    ('2014-10-20'),
    ('2014-10-21');

您如何将这些日期聚合成连续的日期范围(没有间隔的范围)?如:

 start_date | end_date
------------+------------
 2014-10-11 | 2014-10-13
 2014-10-15 | 2014-10-16
 2014-10-18 | 2014-10-18
 2014-10-20 | 2014-10-21

这是我目前想出的,但我只能通过这种方式获得start_date

WITH reserved_date_ranges AS (
    SELECT reserved_date,
           reserved_date
           - LAG(reserved_date) OVER (ORDER BY reserved_date) AS difference
    FROM reserved_dates
)
SELECT *
FROM reserved_date_ranges
WHERE difference > 1 OR difference IS NULL;

【问题讨论】:

  • 关键字是 calendar table ,在你的情况下:: generate_series() left join YourTable,基本上。
  • 好吧,我会这样用中间日期来填补空白。我如何从中获取日期范围?

标签: sql postgresql time-series aggregate-functions window-functions


【解决方案1】:
SELECT min(reserved_date) AS start_date
     , max(reserved_date) AS end_date
FROM  (
   SELECT reserved_date
        , reserved_date - row_number() OVER (ORDER BY reserved_date)::int AS grp
   FROM   reserved_dates
   ) sub 
GROUP  BY grp
ORDER  BY grp;
  1. 使用窗口函数 row_number() 按时间顺序计算运行中的无间隙数字 - 除非您的 reserved_days_id 恰好是无间隙且按时间顺序排列的,这通常 不是 em> 情况。

  2. 从每行的reserved_date 中减去(转换为integer 后)。连续几天以相同的日期值结束 grp - 除了组成组之外没有其他目的或意义。

  3. 在外部查询中聚合。瞧。

SQL Fiddle.

类似情况:

【讨论】:

  • 这个 A 在一般情况下似乎很难应用于具有设定分辨率的时间序列,例如2 天或每 10 分钟一次。时间戳需要转换为实际值,并且浮点运算并不精确。有替代品吗?
  • 我收回我的话。此解决方案适用于类似于 extract(epoch from timestamp) - extract(epoch from interval '1day')*row_number() over (order by timestamp) 的时间戳列
  • 经过这么多年,我意识到它不是防重复的db-fiddle.com/f/31UdD6udUZqwQk43pRbGKZ/1
  • 如果您碰巧有重复,请使用 dense_rank 而不是 row_number
猜你喜欢
  • 2013-03-24
  • 1970-01-01
  • 1970-01-01
  • 2018-09-02
  • 1970-01-01
  • 2017-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多