我有这样一张桌子:
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
我想选择在10点到11点之间每隔5分钟登录一次的用户数量。
我需要这样的结果。
time count
---------------
10:05 2
10:20 2
10:30 1
10:35 1
如何编写用于创建此类结果的MySQL查询?
答案 0 :(得分: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)
答案 1 :(得分: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 ... AND来加入。替代设计将使用范围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之间基本上是不标准化的。
答案 2 :(得分:1)
如果你想让它显示用户分别登录的5分钟间隔,只需将(分钟/ 5)的INTEGER除以然后乘以5. Ex: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的整个日期范围,否则您可能会遗漏某些预期的数据
答案 3 :(得分:0)
我不知道你现在怎么做,我必须更多地考虑你需要的结果。但是你必须在Mysql中使用timediff
函数
示例:
SELECT TIMEDIFF('2009-02-01 00:00:00', '2009-01-01 00:00:00');
绝对必须在MySQL查询中使用for循环来计算每5分钟所需的结果。
答案 4 :(得分: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