我需要一个通用函数来检查两个时间范围是否在同一天内重叠,该函数还适用于计划从午夜之前开始到午夜之后结束的情况,例如"17:00:00-03:00:00"和"14: 00:00-01:00:00"应该重叠,因此我修改了Bohemian的解决方案(链接)
您可以按以下方式使用此函数
SELECT func_time_overlap("17:00:00","03:00:00", "14:00:00","01:00:00")
或者在你的情况下像这样。
SELECT *
FROM mytable a
JOIN mytable b ON (
a.name != b.name
AND func_time_overlap(a.starttime, a.endtime, b.starttime, b.endtime)
);
以下是函数定义
CREATE FUNCTION `func_time_overlap`(a_start TIME, a_end TIME, b_start TIME, b_end TIME)
RETURNS tinyint(1)
DETERMINISTIC
BEGIN
IF a_start >= 24 THEN
SET a_start = TIME(CONCAT(MOD(HOUR(a_start), 24),':',MINUTE(a_start),':',SECOND(a_start)));
END IF;
IF b_start >= 24 THEN
SET b_start = TIME(CONCAT(MOD(HOUR(b_start), 24),':',MINUTE(b_start),':',SECOND(b_start)));
END IF;
IF a_end > 24 THEN
SET a_end = TIME(CONCAT(MOD(HOUR(a_end), 24),':',MINUTE(a_end),':',SECOND(a_end)));
END IF;
IF b_end > 24 THEN
SET b_end = TIME(CONCAT(MOD(HOUR(b_end), 24),':',MINUTE(b_end),':',SECOND(b_end)));
END IF;
IF a_start >= a_end THEN
SET a_end = a_end + INTERVAL 24 HOUR;
END IF;
IF b_start >= b_end THEN
SET b_end = b_end + INTERVAL 24 HOUR;
END IF;
RETURN a_start < b_end AND a_end > b_start;
END
我不使用
TIME(CAST(a_start AS DATETIME));
将时间间隔转换为时间,因为它默认使用当前日期,并可能受到数据库时区设置的影响,想象一下下一天有夏令时改变,会出现什么情况。
如果您的数据库使用UTC时区(应该如此),则可以使用以下方法:
IF a_start >= 24 THEN
SET a_start = TIME(CAST(a_start AS DATETIME));
END IF;
IF b_start >= 24 THEN
SET b_start = TIME(CAST(b_start AS DATETIME));
END IF;
IF a_end > 24 THEN
SET a_end = TIME(CAST(a_end AS DATETIME));
END IF;
IF b_end > 24 THEN
SET b_end = TIME(CAST(b_end AS DATETIME));
END IF;
TIME
没有时代秒数,因为它不是DATETIME
。 - Timo Huovinen小时 * 60 + 分钟
。 - BohemianTIME
类型比较,我不明白它如何解决传递为00:00的时间实际上表示24:00或查看另一个情况"17:00:00-03:00:00", "14:00:00-01:00:00"
成为SELECT 61200 <= 3600 and 10800 >= 50400
,这是错误的,尽管它们重叠。 - Timo HuovinenMOD
或CAST
将时间间隔转换为日期时间格式,对于结束时间早于开始时间的情况,只需添加 24 小时(因为实际上就是这样),我将其发布为答案,如果您感兴趣,请查看,谢谢您的帮助。 - Timo Huovinen