每小时持续时间的 SQL 计数事件

Posted

技术标签:

【中文标题】每小时持续时间的 SQL 计数事件【英文标题】:SQL Count events with duration per hour 【发布时间】:2020-05-05 18:28:28 【问题描述】:

我有一个事件的持续时间数据(例如,在餐厅吃饭),我想知道在任何给定小时内发生了多少事件。数据如下所示:

Event     |   Start Time    |   End Time
-----------------------------------------
  1       |   12:03         |   14:20
  2       |   12:30         |   12:50
  3       |   13:05         |   14:45
  4       |   14:01         |   14:49

我还可以使用“持续时间”来替代“结束时间”。我正在寻找的结果是这样的:

  Hour     |     Count
-----------------------
   12      |     2
   13      |     2
   14      |     3

在第 12 小时,发生了两个事件(1 和 2),第 13 小时也发生了两个事件(1 和 3),第 14 小时发生了三个事件(1、3 和 4)。

我可以通过循环以编程方式执行此操作。我可以在 SQL 中计算事件开始(或结束)的时间。但是我真的很想缩小差距并在 SQL 中做到这一点,但我想不出办法。

【问题讨论】:

【参考方案1】:

一种可能的解决方案(适用于 mysql v5.6+ 和 SQLite3):

create table hours(Hour int);
insert into hours values
  (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),
  (13),(14),(15),(16),(17),(18),(19),(20),(21),(22),(23);

create table log(Event int,StartTime varchar(5),EndTime varchar(5));
insert into log values
  (1,'12:03','14:20'),
  (2,'12:30','12:50'),
  (3,'13:05','14:45'),
  (4,'14:01','14:49');

-- ------------------------------------------------------------------------------

select Hour,count(Event) Count
  from log join hours
    on Hour between substr(StartTime,1,2) and substr(EndTime,1,2)
  group by Hour;

【讨论】:

聪明!这将一直有效,直到我可以让我的 ISP 更新 Maria DB 并使用@GMB 的解决方案。【参考方案2】:

如果你没有MySql 8,那么创建一个表hour

CREATE TABLE hour (
  hr INT PRIMARY KEY
);

INSERT INTO hour(hr) VALUES
    (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),
    (12),(13),(14),(15),(16),(17),(18),(19),(20),(21),(22),(23);

然后:

select h.hr, count(*) as cnt from hour h
join mytable m on h.hr between hour(m.Start_Time) and hour(m.End_Time)
group by hr
order by hr
;

See Db-Fiddle

【讨论】:

【参考方案3】:

如果您运行的是 MySQL 8.0,您可以使用UNION ALL、窗口函数和聚合,如下所示:

select hr, sum(sum(cnt)) over(order by hr) cnt
from (
    select hour(start_time) hr, 1 cnt from mytable
    union all select hour(end_time) + 1, -1 from mytable
) t
group by hr

Demo on DB Fiddle

小时 | cnt -: | --: 12 | 2 13 | 2 14 | 3 15 | 0

【讨论】:

太棒了!现在我只需要让我的 ISP 升级到 MariaDB 10.2。它们仍在 10.1 上,就在引入窗口函数之前。谢谢!!

以上是关于每小时持续时间的 SQL 计数事件的主要内容,如果未能解决你的问题,请参考以下文章

SQL 按小时获取不同的客户计数

如何在两次之间添加每小时计数

使用 Python 进行每小时频率计数

时间间隔内的 SQL 计数

CakePHP 中的多重计数

SQL 查询 - 两个计数不同的粒度