【问题标题】:Displaying aggregate data per hour每小时显示汇总数据
【发布时间】:2017-10-08 15:31:37
【问题描述】:

我有一个 MySQL 数据库,其中包含一个包含时间戳登录的表,我想获取过去 24 小时内每小时的登录次数。

起初,我尝试了一些显而易见的事情:

SELECT
  timestamp AS Hour,
  COUNT(*) AS Logins
FROM auth
WHERE
  timestamp >= DATE_SUB(NOW(), INTERVAL 1 DAY)
GROUP BY HOUR(timestamp)
ORDER BY timestamp DESC

这会产生类似于以下内容的输出:

+---------------------+--------+
| Hour                | Logins |
+---------------------+--------+
| 2017-10-08 17:00:05 |    272 |
| 2017-10-08 16:00:02 |    323 |
| 2017-10-08 15:00:34 |    301 |
| 2017-10-08 14:55:10 |     30 |
| 2017-10-08 11:04:27 |    107 |
| 2017-10-08 10:06:26 |    115 |
| 2017-10-08 09:00:11 |     92 |
| 2017-10-08 08:02:34 |    195 |
| 2017-10-08 07:03:15 |    171 |
| 2017-10-08 06:03:06 |    133 |
| 2017-10-08 05:00:20 |    102 |
| 2017-10-08 04:03:23 |    198 |
| 2017-10-08 03:00:23 |    345 |
| 2017-10-08 02:01:39 |    318 |
| 2017-10-08 01:01:22 |    205 |
| 2017-10-08 00:00:24 |    334 |
| 2017-10-07 23:00:00 |    501 |
| 2017-10-07 22:00:10 |    377 |
| 2017-10-07 21:00:02 |    482 |
| 2017-10-07 20:00:04 |    349 |
| 2017-10-07 19:00:54 |    298 |
| 2017-10-07 18:13:06 |    438 |
+---------------------+--------+
22 rows in set (0,02 sec)

这个输出有两个问题。第一个是时间戳不是整个小时,因为第一次登录发生在确切的小时后几分钟/秒。另外,我真的不需要输出中的日期。我通过执行以下操作解决了这个问题:

SELECT
  DATE_FORMAT(DATE_ADD(timestamp, INTERVAL 30 MINUTE),'%H:00:00') AS Hour,
  COUNT(*) AS Logins
FROM auth
WHERE
  timestamp >= DATE_SUB(NOW(), INTERVAL 1 DAY)
GROUP BY HOUR(timestamp)
ORDER BY timestamp DESC

现在的输出是

+----------+--------+
| Hour     | Logins |
+----------+--------+
| 17:00:00 |    272 |
| 16:00:00 |    323 |
| 15:00:00 |    301 |
| 15:00:00 |     30 |
| 11:00:00 |    107 |
| 10:00:00 |    115 |
| 09:00:00 |     92 |
| 08:00:00 |    195 |
| 07:00:00 |    171 |
| 06:00:00 |    133 |
| 05:00:00 |    102 |
| 04:00:00 |    198 |
| 03:00:00 |    345 |
| 02:00:00 |    318 |
| 01:00:00 |    205 |
| 00:00:00 |    334 |
| 23:00:00 |    501 |
| 22:00:00 |    377 |
| 21:00:00 |    482 |
| 20:00:00 |    349 |
| 19:00:00 |    298 |
| 18:00:00 |    452 |
+----------+--------+
22 rows in set (0,00 sec)

问题 #1:这是一种很好的方法(显示整个小时)还是有更好的方法?

第二个问题我不知道怎么解决。你看,上面的命令是在当地时间 18:19 执行的。请注意,缺少 18:00 到 18:19 之间的登录次数。是的,我知道最后一小时还没有结束,但我仍然想显示在过去的那部分中积累的数据。

问题 #2:如何做到这一点?

【问题讨论】:

  • 我倾向于认为将除您选择的东西以外的任何东西分组是不好的做法。显示问题应在应用程序代码中处理
  • @Strawberry,不确定您的意思。我选择并按timestamp 分组。你的意思是我应该使用HOUR(DATE_ADD(timestamp, INTERVAL 30 MINUTE)) 而不是DATE_FORMAT(DATE_ADD(timestamp, INTERVAL 30 MINUTE),'%H:00:00')?好吧,无论如何,但问题 #2 并不能由此解决。
  • 你为什么要给timestamp加30分钟?
  • @kmoser,你说得对,没必要;只需HOUR(timestamp) 即可。这是我尝试将时间戳转换为一小时的剩余时间。但删除它并不能解决丢失最后(不完整)小时数据的问题。
  • @bontchev 在您的原始帖子中,您写道“请注意,缺少 18:00 到 18:19 之间的登录次数”。这是不正确的。 18:00 行汇总了 18:00 到 18:59:59 之间的所有登录。如果您在 18:19 运行查询,它将包括从 18:00 到 18:19(即当前时间)的登录。

标签: mysql datetime group-by hour


【解决方案1】:

正如@kmoser 指出的那样,问题在于 24 小时期间的最后(不完整)小时的数据与它的第一小时分组 - 因为小时数是相同的。为了解决这个问题,我们需要根据不同日期的相同时间进行分组。这是对我有用的解决方案:

SELECT
  DATE_FORMAT(timestamp, '%Y-%m-%d %H:00:00') AS Hour,
  COUNT(*) AS Logins
FROM auth
WHERE
  timestamp >= DATE_SUB(NOW(), INTERVAL 1 DAY)
GROUP BY DATE_FORMAT(timestamp, '%Y-%m-%d %H:00:00')
ORDER BY timestamp DESC

【讨论】:

    【解决方案2】:
    select count(*) as cnt
    from  auth
    where date >= DATE_SUB(NOW(),INTERVAL 1 HOUR); 
    

    【讨论】:

    • 这个答案非常糟糕,完全错误。你甚至明白这个问题吗?
    猜你喜欢
    • 2011-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-27
    • 2019-10-11
    • 1970-01-01
    相关资源
    最近更新 更多