连续时间片段判断解决方案
场景
一个账号同一个会议室不能连续多天预定(4天)超过4个小时(会议预定开始时间和结束时间不垮天)
schema
create table meeting_room_reserve
(
id bigint auto_increment comment '主键'
primary key,
meeting_room_id bigint null comment '会议室id',
start_time varchar(24) charset utf8 null comment '会议开始时间',
end_time varchar(24) charset utf8 null comment '会议结束时间',
meeting_date varchar(32) charset utf8 null comment '会议日期'
);
思路
- 查出满足预定条件的会议记录(超过4小时、当前账号)
- 即将预定的日期union步骤1查询结果的日期按照预定时间排序
- 查询排序后的日期与前一个日期的时间间隔天数
- 设置group_id, 间隔天数为1的日期与前一天是同一组
- 根据group_id分组, 每组都是一个连续时间区间, 过滤出当前日期所在的分组
- 根据连续时间天数继续过滤,如果不满足要求返回结果是1,满足是0
final solution
select count(*)
from (WITH DateList AS (SELECT #{meetingDate} AS meeting_date
UNION
SELECT meeting_date
FROM t_meeting_pre_form t
WHERE t.create_user = #{userCode}
AND TIMESTAMPDIFF(HOUR, STR_TO_DATE(t.meeting_time_top, '%Y-%m-%d %H:%i:%s'),
STR_TO_DATE(t.meeting_time_bottom, '%Y-%m-%d %H:%i:%s')) > 4
and t.delete_mark = 0
and t.meeting_room_id = #{meetingRoomId}
ORDER BY meeting_date),
RankedDates AS (SELECT meeting_date,
DATEDIFF(meeting_date,
LAG(meeting_date) OVER (ORDER BY meeting_date)) AS date_diff
FROM DateList),
ConsecutiveGroups AS (SELECT meeting_date,
SUM(IF(date_diff = 1, 0, 1))
OVER (ORDER BY meeting_date) AS group_id
FROM RankedDates)
SELECT group_id, MIN(meeting_date) AS start_date, MAX(meeting_date) AS end_date
FROM ConsecutiveGroups
GROUP BY group_id
HAVING DATEDIFF(MAX(meeting_date), MIN(meeting_date)) >= 3
and str_to_date(#{meetingDate}, '%Y-%m-%d') between str_to_date(start_date, '%Y-%m-%d') and str_to_date(end_date, '%Y-%m-%d')) as tmp