查找连续日期流中的每个第n个日期

ret*_*.at 4 sql postgresql

我想在给定日期范围内为每个用户插入到我的表中的连续日期流中每隔4天查找/标记一次

CREATE TABLE mytable (
  id INTEGER,
  myuser INTEGER,            
  day DATE NOT NULL,
  PRIMARY KEY  (id)      
);
Run Code Online (Sandbox Code Playgroud)

问题是,每个用户只有3天连续有效,之后,必须有一天"休息"

 id  | myuser |    day     |
-----+--------+------------+
  0  |    200 | 2012-01-12 | }
  1  |    200 | 2012-01-13 | }--> 3 continuous days
  2  |    200 | 2012-01-14 | }
  3  |    200 | 2012-01-15 | <-- not ok, user 200 should get warned and delete this
  4  |    200 | 2012-01-16 | }
  5  |    200 | 2012-01-17 | }--> 3 continuous days
  6  |    200 | 2012-01-18 | }
  7  |    200 | 2012-01-19 | <-- not ok, user 200 should get warned and delete this
  8  |    201 | 2012-01-12 | }
  9  |    201 | 2012-01-13 | }--> 3 continuous days
  10 |    201 | 2012-01-14 | }
  11 |    201 | 2012-01-16 | <-- ok, there is a one day gap here
  12 |    201 | 2012-01-17 | 
Run Code Online (Sandbox Code Playgroud)

主要目标是查看给定的日期范围(通常是一个月)并确定不允许的日期.此外,我必须注意正确处理重叠日期,例如,如果我查看2012-02-01至2012-02-29的日期范围,2012-02-01可能是一个"休息"日,如果对于同一用户,该表中存在2012-01-29至2012-01-31.

Mat*_*lie 5

我无法访问PostgreSQL,但希望这可行...

WITH
  grouped_data AS
(
  SELECT
    ROW_NUMBER() OVER (PARTITION BY myuser ORDER BY day) - (day - start_date) AS user_group_id,
    myuser,
    day
  FROM
    myTable
  WHERE
        day >= start_date - 3
    AND day <= end_date
)
,
  sequenced_data AS
(
  SELECT
    ROW_NUMBER() OVER (PARTITION BY myuser, user_group_id ORDER BY day) AS sequence_id,
    myuser,
    day
  FROM
    grouped_data
)
SELECT
  myuser,
  day,
  CASE WHEN sequence_id % 4 = 0 THEN 1 ELSE 0 END as should_be_a_break_day
FROM
  sequenced_data
WHERE
  day >= start_date
Run Code Online (Sandbox Code Playgroud)


对不起,我没有解释工作,我不得不跳进会议:)

start_date ='2012-01-14'的示例...

 id | myuser |    day     | ROW_NUMBER() | day - start_date | user_group_id
----+--------+------------+--------------+------------------+---------------
  0 |    200 | 2012-01-12 |     1        |        -2        |  1 - -2 = 3
  1 |    200 | 2012-01-13 |     2        |        -1        |  2 - -1 = 3
  2 |    200 | 2012-01-14 |     3        |         0        |  3 -  0 = 3
  3 |    200 | 2012-01-15 |     4        |         1        |  4 -  1 = 3
  4 |    200 | 2012-01-16 |     5        |         2        |  5 -  2 = 3
----+--------+------------+--------------+------------------+---------------
  5 |    201 | 2012-01-12 |     1        |        -2        |  1 - -2 = 3
  6 |    201 | 2012-01-13 |     2        |        -1        |  2 - -1 = 3
  7 |    201 | 2012-01-14 |     3        |         0        |  3 - -1 = 3
  8 |    201 | 2012-01-16 |     4        |         2        |  4 -  2 = 2
Run Code Online (Sandbox Code Playgroud)

任何连续日期都将具有相同的user_group_id.日期中的每个"间隙"使得user_group_id减少1 (参见第8行,如果记录是第17个,2天的差距,则id将为1).

一旦你有了group_id,row_number()可以很容易地用来说明序列中的哪一天.最多3天与"每4天应该是间隙"相同,并且"x%4 = 0"每隔4天识别一次.

  • 我们应该提名OVER作为总统:)) (2认同)