绘制一个时间范围内在线人数的图表

时间:2014-03-19 09:45:03

标签: sql postgresql

我有一个存储

的数据库模型
  • 访问时间
  • 上次见面
  • 在线多少秒(派生值,通过减去上次访问时间的时间来计算)

我需要在一段时间范围内(比如说晚上8点到晚上9点)建立一个在线人员图表。我认为x轴是y轴作为人数的时间。图表的粒度为1分钟,但我的数据粒度为5秒。

由于人们在晚上8点之前或之后访问,我不能只计算在线秒数值。

我在考虑加载在特定日期发现的所有记录并在内存中进行计算(我现在可能会这样做,然后只是稍后缓存派生值)但我想知道是否有更高效的方式是什么?

我想知道是否有一个特殊的SQL查询组,我可以做的就是让它工作。

编辑:这是我从另一个问题(Count Grouped Gaps In Time For Time Range)窃取的图形表示:P

   |.=========]
                     |.=============]
            |=========.======]
|===.=================.====]
   |.=================.==========]

T   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 

条形图表示我存储的数据(访问时间,上次查看时间和在线秒数),我需要知道在特定点上有多少在线。在这个例子中,对于T = 0,数字是3,对于T = 9,数字是4)

问:我无法理解您的意思“但我的数据精确到5秒”,您每次访问存储了多少条记录?你能添加一些示例数据吗?

答:每次访问只有一条记录。粒度为5秒意味着我存储了长达5秒的准确数据。

按要求提供样本数据:

id     visit_time      last_seen_time        seconds_online
1      00:00:00        00:00:12              10
2      00:12:41        00:12:47               5
3      00:01:20        00:01:22               0
4      00:01:22        00:01:27               5

在这种特殊情况下,如果我在00:00:00在线绘制人物,那么会有一个人,直到00:00:15才有0人:

 4|
 3|
 2|      *
 1|*                        *
   -*****-******************-

1 个答案:

答案 0 :(得分:0)

非常有趣且难以回答的问题,如果我们假设图表的间隔应该是按小时(例如从8.00到8.59),并且按分钟的粒度,我们可以通过提取此日期部分来利用问题(如果您正在使用postgresql使用的函数应该是EXTRACT),我也建议使用Commont Table Expressions。

然后我们可以建立一个CTE,以便在目标时间内每次访问的第一分钟和最后一分钟,例如:

SELECT CASE WHEN EXTRACT(hour FROM visit_time) = 8 
            THEN EXTRACT(minute FROM visit_time) 
            ELSE 0 END AS first_minute,
       CASE WHEN EXTRACT(hour FROM last_seen_time) = 8
            THEN EXTRACT(minute FROM last_seen_time)
            ELSE 59 END AS last_minute
  FROM visit_table
 WHERE EXTRACT(hour FROM visit_time) <= 8 AND EXTRACT(hour FROM last_seen_time) >= 8

新访问开始或访问结束时访问者更改的次数,因此我们可以从第一次开始构建第二次CTE,以获得访问者所有分钟的列表。数字更改,让名为target的第一个CTE,然后后者可以定义为:

SELECT first_minute AS minute
  FROM target
UNION
SELECT last_minute AS minute
  FROM target

UNION也会消除重复。 最后,我们可以加入这两个表并统计访问者:

WITH target AS (
        SELECT CASE WHEN EXTRACT(hour FROM visit_time) = 8 
                    THEN EXTRACT(minute FROM visit_time) 
                    ELSE 0 END AS first_minute,
               CASE WHEN EXTRACT(hour FROM last_seen_time) = 8
                    THEN EXTRACT(minute FROM last_seen_time)
                    ELSE 59 END AS last_minute
          FROM visit_table
         WHERE     EXTRACT(hour FROM visit_time) <= 8
               AND EXTRACT(hour FROM last_seen_time) >= 8
     ), time_table AS (
        SELECT first_minute AS minute
          FROM target
        UNION
        SELECT last_minute AS minute
          FROM target
     )
SELECT time_table.minute, COUNT(*) AS Users
  FROM target INNER JOIN
       time_table ON time_table.minute BETWEEN target.first_minute
                                           AND target.last_minute
 GROUP BY time_table.minute
 ORDER BY time_table.minute

你应该获得一张表,其中第一条记录包含第一分钟,在目标小时内,当至少有一个在线访问者时,有在线人数,然后你有一个记录每次更改的数量在线人员,随着变化的分钟和新的在线人数,您可以轻松地从中创建图表。

很抱歉,如果我无法测试此解决方案,但我希望无论如何它都能为您提供帮助。