MySQL分组总计

时间:2014-04-25 14:22:10

标签: mysql sql grouping

我只知道SQL的基础知识。我有一个数据库,显示一个人何时进入办公室以及何时离开。

e.g

Name     Enter                    Exit
Jack     2014-01-01 01:00:00     2014-01-01 02:00:00
Sam      2014-01-01 02:00:00     2014-01-01 03:00:00
Jane     2014-01-01 02:00:00     2014-01-01 03:00:00
Judy     2014-01-01 03:00:00     2014-01-01 04:00:00

我要做的是按小时查找办公室中的用户总数,按小时分组,也可以按日期分组,所以我的结果应该是

date           hour   Occupancy
2014-01-01     1       1
2014-01-01     2       3
2014-01-01     3       3
2014-01-01     4       1

**** EDIT

我可以将数据库设置为仅收集小时并丢弃会议记录,但是一个人也可以在两天之后进入和离开。所以我正在寻找的东西不仅仅是进入和退出一小时。

1 个答案:

答案 0 :(得分:1)

更新回答:

好的,我调整了您的样本数据,以反映输入和退出日期不在同一天且输入和退出时间相差超过一小时的情况。

CREATE TABLE t
    (`Name` varchar(4), `Enter` datetime, `Exit` datetime)
;

INSERT INTO t
    (`Name`, `Enter`, `Exit`)
VALUES
    ('Jack', '2014-01-01 01:00:00', '2014-01-01 02:00:00'),
    ('Sam', '2014-01-01 02:00:00', '2014-01-01 05:00:00'),
    ('Jane', '2014-01-01 02:00:00', '2014-01-01 03:00:00'),
    ('Judy', '2014-01-01 03:00:00', '2014-01-03 04:00:00')
;

为了方便起见,我创建了一个包含我们样本数据的日期范围的表格。

drop table if exists n;
create table n(a int auto_increment primary key, b datetime);
insert into n (a) values(null), (null);

insert into n (a)
select null from n n1, n n2, n n3, n n4, n n5, n n6;

这个快速黑客在我们的表中插入了66个数字。接下来,我生成覆盖样本数据的日期。

update n 
set b = '2014-01-01 00:00:00' + interval a hour;

既然我们在2014-01-01 00:00:002014-01-03 18:00:00之间的每整个小时都有日期时间值,我们就可以使用此表简单地加入它。

select date(n.b), hour(n.b), count(*)
from
t inner join n on n.b between t.Enter and t.Exit
group by 1, 2

这样我们就可以获得进入和退出时间之间每隔一小时的记录。结果是:

|       DATE | HOUR | COUNT(*) |
|------------|------|----------|
| 2014-01-01 |    1 |        1 |
| 2014-01-01 |    2 |        3 |
| 2014-01-01 |    3 |        3 |
| 2014-01-01 |    4 |        2 |
| 2014-01-01 |    5 |        2 |
| 2014-01-01 |    6 |        1 |
| 2014-01-01 |    7 |        1 |
| 2014-01-01 |    8 |        1 |
| 2014-01-01 |    9 |        1 |
| 2014-01-01 |   10 |        1 |
| 2014-01-01 |   11 |        1 |
| 2014-01-01 |   12 |        1 |
| 2014-01-01 |   13 |        1 |
| 2014-01-01 |   14 |        1 |
| 2014-01-01 |   15 |        1 |
| 2014-01-01 |   16 |        1 |
| 2014-01-01 |   17 |        1 |
| 2014-01-01 |   18 |        1 |
| 2014-01-01 |   19 |        1 |
| 2014-01-01 |   20 |        1 |
| 2014-01-01 |   21 |        1 |
| 2014-01-01 |   22 |        1 |
| 2014-01-01 |   23 |        1 |
| 2014-01-02 |    0 |        1 |
| 2014-01-02 |    1 |        1 |
| 2014-01-02 |    2 |        1 |
| 2014-01-02 |    3 |        1 |
| 2014-01-02 |    4 |        1 |
| 2014-01-02 |    5 |        1 |
| 2014-01-02 |    6 |        1 |
| 2014-01-02 |    7 |        1 |
| 2014-01-02 |    8 |        1 |
| 2014-01-02 |    9 |        1 |
| 2014-01-02 |   10 |        1 |
| 2014-01-02 |   11 |        1 |
| 2014-01-02 |   12 |        1 |
| 2014-01-02 |   13 |        1 |
| 2014-01-02 |   14 |        1 |
| 2014-01-02 |   15 |        1 |
| 2014-01-02 |   16 |        1 |
| 2014-01-02 |   17 |        1 |
| 2014-01-02 |   18 |        1 |
| 2014-01-02 |   19 |        1 |
| 2014-01-02 |   20 |        1 |
| 2014-01-02 |   21 |        1 |
| 2014-01-02 |   22 |        1 |
| 2014-01-02 |   23 |        1 |
| 2014-01-03 |    0 |        1 |
| 2014-01-03 |    1 |        1 |
| 2014-01-03 |    2 |        1 |
| 2014-01-03 |    3 |        1 |
| 2014-01-03 |    4 |        1 |

当然你必须调整帮助表。这对帮助桌子肯定不是一件坏事。

再次,这是一个 sqlfiddle ,看它是否正常工作。


原始回答:

select date(a), hour(a), count(*)
from (
    select enter as a from t
    union all
    select `exit` as a from t
) b
group by 1, 2

但请注意,有一些假设。

  1. 时间总是一整小时
  2. 输入和退出日期始终在同一天
  3. 输入和退出时间仅在一小时内有所不同
  4. 如果其中一个假设不正确,那就会变得更加复杂