汇总连续的日期范围

Lin*_*nas 6 sql postgresql time-series aggregate-functions window-functions

假设您有以下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');
Run Code Online (Sandbox Code Playgroud)

如何将这些日期汇总到连续日期范围(没有间隙的范围)?如:

 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
Run Code Online (Sandbox Code Playgroud)

这是我到目前为止所提出的,但我只能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;
Run Code Online (Sandbox Code Playgroud)

Erw*_*ter 8

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;
Run Code Online (Sandbox Code Playgroud)
  1. 使用窗函数按时间顺序计算一个正在运行的无间隙数row_number()- 除非你reserved_days_id恰好是无间隙且按时间顺序排列,通常不是这种情况.

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

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

SQL小提琴.

类似案例:

  • 如果碰巧有重复项,请使用“dense_rank”而不是“row_number”。 (2认同)