求调度日历行高计算的SQL方案:统计重叠记录数适配CSS高度
SQL解决方案:统计时间段最大重叠行数
假设表结构
先假设你的船舶调度表结构如下(可根据实际表名/字段名调整):
CREATE TABLE ship_schedules ( ship_id INT, start_date DATE, end_date DATE, -- 其他字段如船舶名称、任务类型等 );
核心SQL查询
以下SQL会统计指定时间范围内(比如2023-02-05至2023-02-08)的最大重叠记录数,也就是你需要的行高依据值:
WITH event_points AS ( -- 拆分每条记录为"开始"和"结束"两个事件 SELECT start_date AS event_date, 1 AS event_type FROM ship_schedules WHERE start_date <= '2023-02-08' AND end_date >= '2023-02-05' UNION ALL SELECT end_date + INTERVAL 1 DAY AS event_date, -1 AS event_type FROM ship_schedules WHERE start_date <= '2023-02-08' AND end_date >= '2023-02-05' ), running_counts AS ( -- 按事件日期排序,计算累计重叠数 SELECT event_date, SUM(event_type) OVER (ORDER BY event_date) AS current_overlap FROM event_points ) -- 取最大重叠数,就是需要的结果 SELECT MAX(current_overlap) AS max_overlap_rows FROM running_counts;
逻辑说明
- 事件拆分:把每条调度记录拆成「开始日期+1」和「结束日期+1天-1」的事件——给结束日期加1天是因为如果A记录到2月8日结束,B记录从2月8日开始,这两条不算重叠,所以结束事件放在次日,确保日期边界判断准确。
- 累计计算:按事件日期排序后,用窗口函数累加事件类型(开始加1,结束减1),得到每个时间点的当前重叠记录数。
- 取最大值:最终的最大累计值就是该时间段内同时存在的最多记录数,也就是你需要用来计算行高的数值。
与JavaScript结合的思路
- 后端执行上述SQL,将
max_overlap_rows的结果返回给前端(比如通过接口JSON、内嵌脚本变量等方式)。 - 前端JavaScript中,根据这个最大值计算日历行的CSS高度:
// 假设基础行高为40px(可根据实际UI调整) const baseRowHeight = 40; // 从后端获取的最大重叠数 const maxOverlap = 3; // 计算最终行高 const calendarRowHeight = baseRowHeight * maxOverlap; // 给日历行设置高度 document.querySelectorAll('.calendar-row').forEach(row => { row.style.height = `${calendarRowHeight}px`; });
扩展说明
- 如果需要按天统计每天的最大重叠数(而非整个时间段),可以在
running_counts中按日期分组后取每天的最大值,再整体取最大。 - 若你的日期字段包含时间(如DATETIME类型),只需去掉
DATE转换,直接用原字段即可,逻辑完全通用。
内容的提问来源于stack exchange,提问作者Fandango68
相关产品推荐
相关产品推荐

