Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 查询最大同时事件数_Sql_Mysql_Postgresql - Fatal编程技术网

Sql 查询最大同时事件数

Sql 查询最大同时事件数,sql,mysql,postgresql,Sql,Mysql,Postgresql,我有一个简单的事件表: event_id | start_time | end_time 如何查询同时发生的最大事件数 我会多次这样做,这是一个非常缓慢的解决方案,但可能没有非常快速的方法。基于Daniel Paull的答案的解决方案会快得多 按开始时间对事件进行排序。 循环浏览事件,找出没有事件的间隔,并将这些间隔之间的事件分组。 在每个组中循环每次(以记录时间的任何分辨率),并查询当时正在进行的事件。根据编程语言的速度与数据库查询的速度,您可以查看重叠事件,并向前跳到其中一个重叠事件的第一

我有一个简单的事件表:

event_id | start_time | end_time

如何查询同时发生的最大事件数

我会多次这样做,这是一个非常缓慢的解决方案,但可能没有非常快速的方法。基于Daniel Paull的答案的解决方案会快得多

按开始时间对事件进行排序。 循环浏览事件,找出没有事件的间隔,并将这些间隔之间的事件分组。
在每个组中循环每次(以记录时间的任何分辨率),并查询当时正在进行的事件。根据编程语言的速度与数据库查询的速度,您可以查看重叠事件,并向前跳到其中一个重叠事件的第一个结束时间。

根据您所指的同步,如其他答案所述,这可能与


不幸的是,我提出的解决方案(这是公认的答案)要求您重新设计表。但是,它可以让您通过检查“SessionCount”(或类似名称)列来轻松确定同时事件的最大数量。

因为您的高峰时间总是在结束时间结束,所以您可以像Spar建议的那样检查这些时间。因此,请执行一个查询,将同一个表联接两次,并计算事件在每个结束时间重叠的行数。那就尽情享受吧

这将给出您的答案,但速度较慢:

SELECT MAX(overlapAtEnd)
FROM
(
    SELECT 
        COUNT(1) AS overlapAtEnd            
    FROM 
        your_table AS t1, 
        your_table AS t2
    WHERE 
        t1.end_time BETWEEN t2.start_time AND t2.end_time
    GROUP BY t1.event_id
) AS foo
将其分成更小的组(比较起来更少),然后获得这些较小组的最大值,可以显著加快速度:

SELECT MAX(maxOLP)
FROM
(
    SELECT MAX(olp) AS maxOLP
    FROM
    (
        SELECT 
            MAX(overlapAtEnd) AS maxOLP,
            EXTRACT(HOUR FROM t1.end_time)  AS hr
        FROM
        (
            SELECT 
                COUNT(1) AS overlapAtEnd            
            FROM 
                your_table AS t1, 
                your_table AS t2
            WHERE 
                t1.end_time BETWEEN t2.start_time AND t2.end_time
            GROUP BY t1.event_id
        ) AS foo
        GROUP BY t1.event_id, EXTRACT(HOUR FROM t1.end_time)
    ) AS foo
    GROUP BY hr
) AS foo2

这种更快的方法有一个小缺点。。。如果你的活动通常跨越一个多小时,那么在下一个小时结束的活动可能仍会重叠,但不会被计算在内。要解决这个问题,只需按更大的间隔分组,如一天或一周。有点毛茸茸的,但效果很好,很快就会给你你想要的结果。

我的答案与哈利的第一个答案非常相似。我会尝试做一个稍微不同的性能优化,虽然。。。跳到结尾,避免对原因进行漫无边际的解释

哈利的第一个答案(核心逻辑)

处理时间最长的地方是连接

对于表中的每条记录,您可以选择(t1.end time)。然后再次在表中搜索(t1.end\u time>=start\u time)和搜索的所有匹配记录(t1.end\u time=start\u time),搜索速度要快得多
-索引是用于极快搜索的搜索树
-这使得查找第一条匹配记录非常快
-索引基本上是有序的
-这意味着它知道“第一场比赛后的一切也都匹配”

最后一部分是关键,因为它意味着。。。即使在使用索引进行第一次检查(t1.end\u time>=start\u time)之后,我们仍然可以留下大量记录来进行第二次检查(t1.end\u time=t2.start\u time)
和t1.end_time“同时事件”的定义是什么?间隔是什么?“同时”显然意味着“同时”非常有趣。“同时”可能意味着毫秒、秒、分钟、小时……很明显,在这种情况下,“事件”发生在一段时间内,所以“同时事件”这个术语有点误导性,因为一个事件通常与一个时间点相关联。我认为他可以通过编程方式构建你答案中描述的表,这需要构建两个交错的++和--events列表。这是一个非常相关的问题的极好链接。我对e上面提到的缺点。事实证明,它是100%准确的,并且不排除任何事件(无论您按什么时间间隔分组)。
SELECT MAX(overlapAtEnd)
FROM
(
    SELECT 
        COUNT(1) AS overlapAtEnd                        
    FROM 
        your_table AS t1, 
        your_table AS t2
    WHERE 
        t1.end_time BETWEEN t2.start_time AND t2.end_time
    GROUP BY t1.event_id
) AS foo
0, '10:00', '10:04'   COUNT(*) WHERE '10:04' >= start_time  ==  4
1, '10:01', '10:06'   COUNT(*) WHERE '10:06' >= start_time  ==  4
2, '10:02', '10:09'   COUNT(*) WHERE '10:09' >= start_time  ==  5
3, '10:04', '10:07'   COUNT(*) WHERE '10:07' >= start_time  ==  4
4, '10:08', '10:12'   COUNT(*) WHERE '10:12' >= start_time  ==  6
5, '10:12', '10:17'   COUNT(*) WHERE '10:17' >= start_time  ==  7
6, '10:15', '10:18'   COUNT(*) WHERE '10:18' >= start_time  ==  8
7, '10:18', '10:22'   COUNT(*) WHERE '10:22' >= start_time  ==  10
8, '10:19', '10:24'   COUNT(*) WHERE '10:24' >= start_time  ==  10
9, '10:22', '10:25'   COUNT(*) WHERE '10:25' >= start_time  ==  10

=> leaves 68 rows to check the second condition; (t1.end_time <= t1.end_time)
SELECT MAX(overlapAtEnd)
FROM
(
    SELECT 
        COUNT(1) AS overlapAtEnd                        
    FROM 
        your_table AS t1, 
        your_table AS t2
    WHERE 
            t1.end_time >= t2.start_time
        AND t1.end_time <= t2.end_time
        AND t1.end_time <= t2.start_time + [max_event_duration] 
    GROUP BY t1.event_id
) AS foo
0, '10:00', '10:04'   COUNT(*) WHERE '10:04' BETWEEN start_time AND start_time + 8 == 4
1, '10:01', '10:06'   COUNT(*) WHERE '10:06' BETWEEN start_time AND start_time + 8 == 4
2, '10:02', '10:09'   COUNT(*) WHERE '10:09' BETWEEN start_time AND start_time + 8 == 4
3, '10:04', '10:07'   COUNT(*) WHERE '10:07' BETWEEN start_time AND start_time + 8 == 4
4, '10:08', '10:12'   COUNT(*) WHERE '10:12' BETWEEN start_time AND start_time + 8 == 3
5, '10:12', '10:17'   COUNT(*) WHERE '10:17' BETWEEN start_time AND start_time + 8 == 2
6, '10:15', '10:18'   COUNT(*) WHERE '10:18' BETWEEN start_time AND start_time + 8 == 3
7, '10:18', '10:22'   COUNT(*) WHERE '10:22' BETWEEN start_time AND start_time + 8 == 4
8, '10:19', '10:24'   COUNT(*) WHERE '10:24' BETWEEN start_time AND start_time + 8 == 3
9, '10:22', '10:25'   COUNT(*) WHERE '10:25' BETWEEN start_time AND start_time + 8 == 3

=> leaves 34 rows to check the second condition; (t1.end_time <= t1.end_time)
=> thats half the original 68, and on bigger tables the benefit increases...
SELECT
   MAX(overlapAtEnd)
FROM
(
    SELECT 
        COUNT(1) AS overlapAtEnd                        
    FROM 
        your_table AS t1, 
        your_table AS t2
    WHERE 
            t2.start_time <= t1.end_time
        AND t2.start_time >= t1.end_time - (SELECT MAX(end_time - start_time) FROM your_table)
        AND t2.end_time   >= t1.end_time
    GROUP BY t1.event_id
) AS foo