【问题标题】:SQL Count events with duration per hour每小时持续时间的 SQL 计数事件
【发布时间】: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 中做到这一点,但我想不出办法。

【问题讨论】:

    标签: mysql sql date datetime mariadb


    【解决方案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 上,就在引入窗口函数之前。谢谢!!
      猜你喜欢
      • 2018-01-29
      • 2019-07-21
      • 1970-01-01
      • 2013-08-14
      • 1970-01-01
      • 1970-01-01
      • 2014-07-01
      • 2018-08-27
      • 1970-01-01
      相关资源
      最近更新 更多