每小时持续时间的 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 计数事件的主要内容,如果未能解决你的问题,请参考以下文章