Postgres查询日历

时间:2017-10-17 15:48:17

标签: sql postgresql calendar

我正在尝试编写一个查询,以便从简单日历应用的事件查询中检索数据。 表结构如下:

table name: events

Column   |  Type      
---------+-----------
 id      | integer
 start   | timestamp
 end     | timestamp

表格内的数据

id| start               | end
--+---------------------+--------------------
1 | 2017-09-01 12:00:00 | 2017-09-01 12:00:00
2 | 2017-09-03 10:00:00 | 2017-09-03 12:00:00
3 | 2017-09-08 12:00:00 | 2017-09-11 12:00:00
4 | 2017-09-11 12:00:00 | 2017-09-11 12:00:00

预期结果是

 date      | event.id
-----------+---------
2017-09-01 | 1
2017-09-03 | 2
2017-09-08 | 3
2017-09-09 | 3
2017-09-10 | 3
2017-09-11 | 3
2017-09-11 | 4

正如您所看到的,只检索有事件的天数(不仅仅是开始和结束,还有两天之间),根本没有检索到没有事件的日子。 在第二步中,我希望能够限制不同天数,例如“获得4天的活动”可能超过4行。

现在我只能使用以下查询基于开始日期检索事件:

SELECT start::date, id FROM events WHERE events.start::date >= '2017-09-01' LIMIT 3

认为我已经知道DENSE_RANK和generate_series,但到目前为止我还没有办法填补开始和结束之间的空白,但没有找到没有数据的日子。

简而言之: 我想得到的是:在接下来的X天举行活动。包含事件的日期是开始< = date> = end

的日期

有什么想法吗?

修改

感谢Tim我现在有以下查询(修改为使用generate_series而不是表,并使用dense_rank添加了限制):

select date, id FROM (
SELECT 
    DENSE_RANK() OVER (ORDER BY t1.date) as rank,
    t1.date, 
    events.id 
FROM
    generate_series([DATE]::date, [DATE]::date + interval '365 day', '1 day') as t1
INNER JOIN 
    events 
    ON t1.date BETWEEN events.start::date AND events."end"::date
) as t
WHERE rank <= [LIMIT]

这项工作非常好,即使我对这种限制造成的性能影响不是100%肯定

1 个答案:

答案 0 :(得分:2)

我认为您确实需要一个日历表来涵盖数据可能出现的所有日期。在下面的第一个CTE中,我生成了一个涵盖2017年9月份的表格。然后,我们需要做的就是内部加入此日历表,并在给定日期内出现的给定日期的标准事件表。

WITH cte AS (
    SELECT CAST('2017-09-01' AS DATE) + (n || ' day')::INTERVAL AS date
    FROM generate_series(0, 29) n
)

SELECT
    t1.date,
    t2.id
FROM cte t1
INNER JOIN events t2
    ON t1.date BETWEEN CAST(t2.start AS DATE) AND CAST(t2.end AS DATE);

<强>输出:

    date                id
1   01.09.2017 00:00:00 1
2   03.09.2017 00:00:00 2
3   08.09.2017 00:00:00 3
4   09.09.2017 00:00:00 3
5   10.09.2017 00:00:00 3
6   11.09.2017 00:00:00 3
7   11.09.2017 00:00:00 4

在这里演示:

Rextester