【问题标题】:Group by hour for given time range在给定的时间范围内按小时分组
【发布时间】:2017-10-01 07:51:03
【问题描述】:

在给定一个 DATETIME 字段的情况下,找到了几个按小时分组的解决方案。就我而言,我有一个 DATETIME 范围,我需要将结果分组为每小时并获取计数。

我将尝试在下面说明我的表格结构。我的数据表如下。

mysql> select * from access_logger;
+---------+---------------------+---------------------+
| user_id | entered_at          | exit_at             |
+---------+---------------------+---------------------+
|   20178 | 2017-09-11 07:02:35 | 2017-09-11 10:10:09 |
|   18998 | 2017-09-11 08:02:35 | 2017-09-11 08:41:45 |
|    6754 | 2017-09-11 08:02:35 | 2017-09-11 12:06:42 |
|   18998 | 2017-09-11 09:02:35 | 2017-09-11 13:30:43 |
| // results continues....                            |
+---------+---------------------+---------------------+

根据上面的表格结构,我想看看每小时有多少用户连接到系统。预期的结果是……

+------+-------+
|hours | count |
+------+-------+
|    7 |     1 |
|    8 |     2 |
|    9 |     3 |
|   10 |     3 |
|   11 |     2 |
|   12 |     2 |
|   13 |     1 |
+------+--------

我创建了一个查询,它独立地获取每个小时的结果。

mysql> select "10" as hours, count(user_id) as count 
    -> from access_logger 
    -> where hour(entered_at) <=10 and hour(exit_at) >= 10;

+------+-------+
|hours | count |
+------+-------+
|   10 |     3 |
+------+--------

上述查询将只获得一个小时组的输出。如何编写一个查询,在 24 行中创建所有 24 小时的输出?

【问题讨论】:

  • 所以,你不包括日期?
  • 基本上,我不希望结果中的日期而是我需要它来查看用户是否在给定的时间内。
  • 如果mySQL支持你可以探索temportal database

标签: mysql sql datetime group-by


【解决方案1】:

如果您的表(或您的任何其他表)的行数超过 24 行,您就可以将您的查询和

SELECT  @N := @N +1 AS hour 
FROM access_logger , (SELECT @N:=-1) dum LIMIT 23;

发现于 SQL SELECT to get the first N positive integers

i.E.

select a.hour, count(b.user_id) as count 
from access_logger b inner join (SELECT  @N := @N +1 AS hour 
      FROM access_logger , (SELECT @N:=-1) dum LIMIT 23) a on 
hour(entered_at) <= a.hour and hour(exit_at) >= a.hour;

抱歉,手头没有mysql,所以这里没有测试

【讨论】:

  • 这个查询很好用。我只是加了一些盐。 select a.hour, count(b.mac) as count from ezc_device_history b inner join (SELECT @N := @N +1 AS hour FROM ezc_device_history , (SELECT @N:=-1) dum LIMIT 24) a on hour(entered_at) &lt;= a.hour and hour(exit_at) &gt;= a.hour group by a.hour;
【解决方案2】:

你需要使用HOUR分组

SELECT HOUR(entered_at) AS Hours, COUNT(user_id) AS Total_Users    
FROM access_logger
GROUP BY HOUR(entered_at);

已编辑 ==

您可以创建一个存储过程,在其中计算start_timeend_time 之间每小时的总用户数

begin
p1 INT;
SET p1=1;
counter LOOP

    select @p1 as Hours, count(*) as total_user 
    from access_logger 
    where @p1 between hour(start) and hour(end) ;

    SET p1 = p1 + 1;

    IF p1=24 THEN
       LEAVE counter;
    END IF;
END LOOP counter;
end;

【讨论】:

  • 这是一个很好的解决方案如果有一个单独的日期时间字段并且需要查看用户登录是否属于给定的时间。就我而言,我需要查看用户的持续时间是否在给定的小时内。根据此查询,任何用户在 10:00 进入并在 12:00 退出都不会落入小时 (11)。
  • @BlueBird 我没听懂你。你能把这个要求附上解释吗?
  • 如果你看看我上面的问题。我已经给出了样本记录和预期的结果。它描述了一切。例如,假设您在上午 10 点进入并在晚上 2:30 下午退出。因此,您将在所有(10、11、12、13 和 14)小时内跌倒。你明白我的意思了吗?
  • @BlueBird 不确定,如果在 SQL 中可行
  • @BlueBird 你可以查看我的帖子。我还没有测试过。但是,它会给你一些想法,并随时更新我的​​帖子。
【解决方案3】:

这是一个疯狂的工程答案,使用临时表和 UNION ALL 查询。这当然不适用于数百万行。临时表在 sql 会话期间处于活动状态。如果应用程序服务器使用连接池,您可能希望在查询后删除它。

DROP TEMPORARY TABLE IF EXISTS aTemp;
CREATE TEMPORARY TABLE aTemp ENGINE=memory AS
 (Select hour(entered_at) as enteredH, hour(exited_at) as exitedH From access_logger);

Select '0' as 'hour', count(*) as 'count' From aTemp Where (0 between enteredH and exitedH)
UNION ALL
Select '1' as 'hour', count(*) as 'count' From aTemp Where (1 between enteredH and exitedH)
UNION ALL
Select '2' as 'hour', count(*) as 'count' From aTemp Where (2 between enteredH and exitedH)
UNION ALL
Select '3' as 'hour', count(*) as 'count' From aTemp Where (3 between enteredH and exitedH)
UNION ALL
Select '4' as 'hour', count(*) as 'count' From aTemp Where (4 between enteredH and exitedH)
UNION ALL
Select '5' as 'hour', count(*) as 'count' From aTemp Where (5 between enteredH and exitedH)
UNION ALL
Select '6' as 'hour', count(*) as 'count' From aTemp Where (6 between enteredH and exitedH)
UNION ALL
Select '7' as 'hour', count(*) as 'count' From aTemp Where (7 between enteredH and exitedH)
UNION ALL
Select '8' as 'hour', count(*) as 'count' From aTemp Where (8 between enteredH and exitedH)
UNION ALL
Select '9' as 'hour', count(*) as 'count' From aTemp Where (9 between enteredH and exitedH)
UNION ALL
Select '10' as 'hour', count(*) as 'count' From aTemp Where (10 between enteredH and exitedH)
UNION ALL
Select '11' as 'hour', count(*) as 'count' From aTemp Where (11 between enteredH and exitedH)
UNION ALL
Select '12' as 'hour', count(*) as 'count' From aTemp Where (12 between enteredH and exitedH)
UNION ALL
Select '13' as 'hour', count(*) as 'count' From aTemp Where (13 between enteredH and exitedH)
UNION ALL
Select '14' as 'hour', count(*) as 'count' From aTemp Where (14 between enteredH and exitedH)
UNION ALL
Select '15' as 'hour', count(*) as 'count' From aTemp Where (15 between enteredH and exitedH)
UNION ALL
Select '16' as 'hour', count(*) as 'count' From aTemp Where (16 between enteredH and exitedH)
UNION ALL
Select '17' as 'hour', count(*) as 'count' From aTemp Where (17 between enteredH and exitedH)
UNION ALL
Select '18' as 'hour', count(*) as 'count' From aTemp Where (18 between enteredH and exitedH)
UNION ALL
Select '19' as 'hour', count(*) as 'count' From aTemp Where (19 between enteredH and exitedH)
UNION ALL
Select '20' as 'hour', count(*) as 'count' From aTemp Where (20 between enteredH and exitedH)
UNION ALL
Select '21' as 'hour', count(*) as 'count' From aTemp Where (21 between enteredH and exitedH)
UNION ALL
Select '22' as 'hour', count(*) as 'count' From aTemp Where (22 between enteredH and exitedH)
UNION ALL
Select '23' as 'hour', count(*) as 'count' From aTemp Where (23 between enteredH and exitedH)
;

DROP TEMPORARY TABLE IF EXISTS aTemp;

您可以向(Select hour(entered_at)... From access_logger Where...) 查询添加任何前置过滤器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-19
    • 2011-05-24
    • 1970-01-01
    • 1970-01-01
    • 2020-03-10
    • 2011-06-28
    • 1970-01-01
    相关资源
    最近更新 更多