如何进行optmizied SQL查询以检索每个时间片组中的多个记录

时间:2013-10-17 16:49:40

标签: sql postgresql optimization

我正在使用这个项目的Postgress数据库,但这个问题可以应用于任何数据库。

我需要更有效地从数据库中选择记录。 我有一个表Activity,其中包含在系统上注册的每个活动的记录。

表Activity包含以下列

id             integer 
time_stamp     time stamp without timezone
computer_id    varchar(255)
user_id        varchar(255)
...

一般来说,我需要一个简单的结果。 我需要能够指定5分钟或任何其他时间段的时间片。 并且需要找出每个时间片中是否有任何记录。所以最后我需要每个时间片都有一个真或假的结果。

如果存在True,我需要使用颜色为表格着色,或者为False将其留空。

我制作了一个程序解决方案,通过do while循环并为每个时间片选择一些记录。

例如:

select *
from Activity
where time_stamp between prev_Time and curr_Time 

这有效,但速度很慢。如果时间片是5分钟,则有24小时x 60分钟/ 5分钟= 288个选择查询。

我需要找到一种方法来进行一次快速选择查询。我无法制作存储过程。 甚至更好的是不知道如何用SQL编写给我从开始时间到结束时间的所有时间段,以5分钟为一组。

即使在代码中的任何解决方案都是可以接受的,但必须快速。响应必须最多10秒钟。

1 个答案:

答案 0 :(得分:1)

您可以使用generate_series()函数创建间隔,如下所示:

select g, count(a.id)
from generate_series(
    '20131017 07:00'::timestamp,
    '20131017 08:00'::timestamp,
    '5 minutes'::interval
) as g
   left outer join Activity as a on
      a.time_stamp >= g and a.time_stamp < g + '5 minutes'::interval
group by g
order by g

如果您不需要记录count = 0的记录,则可以使用此查询:

with cte as (
    select
        (extract(epoch from time_stamp - '20131017 07:00'::timestamp) / 60)::int / 5 as p
    from Activity
    where time_stamp <= '20131017 08:00'::timestamp  
)
select
    '20131017 07:00'::timestamp + ((p * 5)::text || ' minutes')::interval, count(*)
from cte
group by p

<强> sql fiddle demo