2012-03-05 36 views
0

我有这样的一个表:如何编写MySQL查询以基于时间范围获取计数?

userId  loggedtime 
------------------- 
1  2012-03-05 10:45:59 
2  2012-03-05 10:04:19 
2  2012-03-05 10:05:09 
4  2012-03-05 10:20:24 
3  2012-03-05 10:20:20 
6  2012-03-05 10:30:59 
7  2012-03-05 10:35:59 

我想选择多少用户登录的每个5分钟间隔10点和11点之间。

我需要这种结果。

time  count 
--------------- 
10:05  2 
10:20  2 
10:30  1 
10:35  1 

如何编写MySQL查询来创建这种结果?

+0

不确定你可以单独使用SQL来完成此操作,也许首先按'userId'和'loggedtime'秒排序(时间必须是升序),然后创建一个新数组,循环遍历结果集并比较递增计数器没有超过5分钟限制。当您传递5分钟或达到新的用户标识时,使用用户标识和计数器在数组中创建一个新条目。 – Yaniro 2012-03-05 06:41:25

+0

你的间隔的界限究竟是什么?它看起来好像您要将值10:01:00..10:05:59计为在10:05范围内; 10:06:00..10:10:59为10:10;等等。那是对的吗? – 2012-03-05 06:43:07

+0

是的,你是正确的@jonathan。我如何在两次之间选择数据。例如。如果我需要记录的用户数在过去5分钟之间,直到这一次。你有什么主意吗? – learner 2012-03-05 06:44:16

回答

3

你只需要找出一些独特的东西,这将给你5分钟的间隔。

如果你花时间分钟,并除以5,那么你有独特的东西。例如,你可以GROUP BY CAST(EXTRACT(MINUTE FROM logTime)/ 5 AS unsigned),这会给你5分钟的时间间隔。/5默认情况下不会舍入。

要实际编写您的工作查询,请分阶段尝试。

首先,让我们得到的只是一分钟:

mysql> SELECT userid, EXTRACT(MINUTE FROM loggedtime) as minute from test; 
+--------+--------+ 
| userid | minute | 
+--------+--------+ 
|  1 |  45 | 
|  2 |  4 | 
|  2 |  5 | 
|  4 |  20 | 
|  3 |  20 | 
|  6 |  30 | 
|  7 |  35 | 
+--------+--------+ 
7 rows in set (0.00 sec) 

现在,让我们尝试做一个列值是,每次5分钟间隔您可以按组唯一的。这是分钟除以5,没有舍入(上面的值/ 5):

mysql> select userid, EXTRACT(MINUTE FROM loggedtime) AS minute, CAST(EXTRACT(MINUTE FROM loggedtime)/5 AS unsigned) FROM test; 


+--------+--------+-------------------------------------------------------+ 
| userid | minute | CAST(EXTRACT(MINUTE FROM loggedtime)/5 AS unsigned) | 
+--------+--------+-------------------------------------------------------+ 
|  1 |  45 |              9 | 
|  2 |  4 |              1 | 
|  2 |  5 |              1 | 
|  4 |  20 |              4 | 
|  3 |  20 |              4 | 
|  6 |  30 |              6 | 
|  7 |  35 |              7 | 
+--------+--------+-------------------------------------------------------+ 
7 rows in set (0.01 sec) 

最后,我们按该唯一列进行分组。此查询使用MIN()和MAX()显示该时间间隔中的第一个和最后一个时间戳,但如果您希望它与您的问题完全相同,则还可以计算截止时间。

mysql> SELECT COUNT(*) AS user_count, MIN(loggedtime) AS first_time, 
MAX(loggedtime) AS last_time 
FROM test 
GROUP BY CAST(EXTRACT(MINUTE FROM loggedtime)/5 AS unsigned) 
ORDER BY last_time; 
+------------+---------------------+---------------------+ 
| user_count | first_time   | last_time   | 
+------------+---------------------+---------------------+ 
|   2 | 2012-03-05 10:04:19 | 2012-03-05 10:05:09 | 
|   2 | 2012-03-05 10:20:20 | 2012-03-05 10:20:24 | 
|   1 | 2012-03-05 10:30:59 | 2012-03-05 10:30:59 | 
|   1 | 2012-03-05 10:35:59 | 2012-03-05 10:35:59 | 
|   1 | 2012-03-05 10:45:59 | 2012-03-05 10:45:59 | 
+------------+---------------------+---------------------+ 
5 rows in set (0.00 sec) 
0

我不知道你现在怎么做,我必须更多地考虑你需要的结果。但是,你必须在MySQL

例如使用timediff功能:

SELECT TIMEDIFF('2009-02-01 00:00:00', '2009-01-01 00:00:00'); 

绝对是你必须使用一个在你循环MySQL查询来计算所需要的结果,每次5分钟。

Look at this too.

+0

嗨如何在两次之间选择数据?例如。如果我需要记录的用户数在过去5分钟之间,直到这一次。你有什么主意吗? – learner 2012-03-05 06:44:09

+0

对不起@learner,我的心目前正在被占领。所以我无法像你想要的那样回答你。但是你必须使用CURRENT_TIME()和TIMEDIFF()函数。在Google上搜索更多关于这些功能的信息。 – 2012-03-05 06:52:55

0

尝试此查询

SELECT 
    loggedTime, 
    count(UserId) 
FROM tableName 
WHERE loggedTime BETWEEN '2010-11-16 10:00:00' AND '2010-11-16 11:00:00' 
GROUP BY 
round(UNIX_TIMESTAMP(timestamp)/300), name 
+0

嗨Naveen。如何在Now()和过去的5分钟之间选择用户数? – learner 2012-03-05 06:51:19

+0

如果你只希望最后五分钟计数'WHERE date_field> date_sub(now(),间隔5分钟) ' – 2012-03-05 07:23:18

2

如果你要进行常规做这样的分析,它可能是值得建立一个表,你的时间间隔。从样本数据和所需的结果来看,我想创建一个表:

Time_Intervals 
I_Start  I_End 
10:01:00  10:05:59 
10:06:00  10:10:59 
10:11:00  10:15:59 
... 
10:56:00  11:00:59 

而且,事实上,它将包含12个间隔每一天的每一个小时(虽然概括为23时56分00秒.. 00:00:59将会出现一些娱乐活动—这是留给读者的练习!)。

然后,您只需使用此表来生成分组:

SELECT i.i_end, COUNT(*) 
    FROM Time_Intervals AS i 
    JOIN ThisKindOfATable AS t 
    ON t.loggedtime BETWEEN i.i_start AND i.i_end 
WHERE t.loggedtime BETWEEN '2012-03-05 10:01:00' AND '2012-03-05 11:00:59' 
GROUP BY i.i_end 
ORDER BY i.i_end; 

我用BETWEEN ...并为加入。另一种设计将使用范围10:01:00 .. 10:06:00和连接条件t.loggedtime >= i.i_start AND t.loggedtime < i.i_end;这可以更好地处理小数秒。

您可能需要对loggedtime进行一些调整,以将其从DATE + TIME转换为仅用于连接条件的TIME(可能是TIME(t.loggedtime))。您也可以调整此值,以便在没有用户使用LEFT JOIN登录的间隔中打印零值,而不是INNER JOIN。您也可能决定放弃时间的几秒钟来简化操作。变化是军团。

主要替代方法是通过适当的计算将给定时间(t.loggedtime值)转换为区间数。这进入了高度DBMS特定的代码 - 操作时间的功能本质上是跨DBMS的非标准化。

1

如果你想让它显示的是用户登录分别在5分钟的时间间隔,仅仅通过5例划分(分钟/ 5)的整数,然后乘:10:03将向下舍到0,次数5代表10:00。 10:05将四舍五入为1 * 5 = 10:05

select 
     concat('10:', LPAD(floor(minute(UL.loggedTime)/5) * 5, 2, '0') as MinuteRange, 
     count(*) as LoginCount 
    from 
     UserLoginTable UL 
    where 
     UL.loggedTime between '2012-03-05 10:00:00' AND '2012-03-05 10:59:59' 
    group by 
     MinuteRange 

是的,它的硬编码的例子,但你也可以从5分钟替换这么多的元素...的时间间隔为10或15(或其它),即使格式化出发'10:”(小时表示)使用方法:

LPAD(小时(UL.LoggedTime),2, '0')

因此,如果你做了较长时间范围...说21:00:00至23:59:59将显示范围内的所有时间。

请注意。由于您与日期/时间列进行比较,所以您只想使用“日期”部分的任何查询,请确保包含从00:00:00到11:59:59的整个日期范围,否则您可能会错过某些预期数据。