MySQL计算单日最小会议房间数:现有方案是否可行?求优解
咱们先拆解下你当前的SQL方案存在的核心问题:
重叠条件判断错误
会议重叠的正确逻辑是两个会议的时间段存在交集,也就是要满足y.start_time < t.end_time AND t.start_time < y.end_time。而你的方案仅用t.start_time between y.start_time and y.end_time判断,只能捕捉到「t的开始时间落在y的时间段内」的场景,会漏掉很多真实的重叠情况:
比如你的测试数据里,会议3(10:00-14:00)和会议2(13:20-15:20)明明在13:20-14:00有重叠,但当t是会议3时,t.start_time=10:00不在会议2的时间段内,导致会议2不会被统计到会议3的分组中,计算出的重叠数和所需房间数明显偏小。未直接输出目标结果
你的需求是计算容纳所有会议的最小房间总数(即整个时间段内同时进行的会议的最大数量),但当前方案返回的是每个会议对应的重叠数据,并没有直接给出这个关键最大值,还需要额外处理才能得到最终结果。
另外,自连接的实现方式时间复杂度是O(n²),当会议数量较多时,性能会明显下降。
计算最小会议房间数的经典思路是时间线扫描法:把所有会议的开始时间标记为「占用房间(+1)」,结束时间标记为「释放房间(-1)」,按时间顺序累加这些标记值,累加过程中的最大值就是同一时刻最多需要的房间数,也就是我们要的最小房间数。
基于窗口函数的实现(MySQL 8.0+支持)
WITH events AS ( -- 拆分所有开始/结束事件,标记房间变化 SELECT start_time AS event_time, 1 AS delta FROM meetings UNION ALL SELECT end_time AS event_time, -1 AS delta FROM meetings ), running_totals AS ( -- 按时间排序,计算累计房间数 SELECT event_time, SUM(delta) OVER (ORDER BY event_time) AS concurrent_meetings FROM events ) -- 取累计房间数的最大值,就是最小需要的房间数 SELECT MAX(concurrent_meetings) AS minimum_rooms_required FROM running_totals;
兼容低版本MySQL的实现(无CTE)
如果你的MySQL版本不支持公共表表达式(CTE),可以用嵌套子查询实现:
SELECT MAX(concurrent_meetings) AS minimum_rooms_required FROM ( SELECT event_time, SUM(delta) OVER (ORDER BY event_time) AS concurrent_meetings FROM ( SELECT start_time AS event_time, 1 AS delta FROM meetings UNION ALL SELECT end_time AS event_time, -1 AS delta FROM meetings ) AS events ) AS running_totals;
方案优势
- 结果准确:正确覆盖所有会议重叠场景,计算出的是真实的最大并发会议数。
- 性能更优:时间复杂度为O(n log n)(主要来自排序操作),远优于自连接的O(n²),数据量越大优势越明显。
- 直接输出结果:一步得到所需的最小房间数,无需额外处理。
针对测试数据的验证
用你的测试数据代入这个方案,拆分后的事件列表按时间累加后,最大并发数是4(14:00-14:05时间段,同时进行会议2、3、4、5),这就是正确的最小房间数。
内容的提问来源于stack exchange,提问作者MontyPython

