在TSQL中跨天查询时段:周内服务时段可用性校验求助
搞定周历时段可用性校验(含跨天场景)
没问题,我来帮你解决这个周历时段校验的问题——尤其是跨天的场景,这确实是这类只存星期规则的表容易踩的坑。你的#Calendar表只记录重复的周时段(没有具体日期),跨天的服务(比如周一19:00到周二07:00)其实是覆盖了两个连续星期几的时间段,所以校验时得分场景处理。
核心逻辑拆解
我们要判断目标校验时段是否和表中已有的服务时段重叠。重叠分两种情况:
- 同天服务:服务的星期和目标时段星期一致,直接判断时间区间是否重叠。
- 跨天服务:服务的
HourStart > HourEnd(比如19:00到07:00),这意味着服务覆盖了当前星期的HourStart到当天结束,加上下一个星期的凌晨到HourEnd。
可直接用的SQL方案
假设我们要校验的目标时段用这几个参数定义(你可以根据实际情况替换):
@CheckStartDay:目标时段开始的星期几(和表中DayWeek格式一致,比如1=周一)@CheckStartTime:目标时段开始时间(TIME类型)@CheckEndDay:目标时段结束的星期几@CheckEndTime:目标时段结束时间(TIME类型)
第一步:先定义测试参数(示例)
-- 比如我们要校验周一20点到周二6点是否可用 DECLARE @CheckStartDay INT = 1, @CheckStartTime TIME = '20:00:00'; DECLARE @CheckEndDay INT = 2, @CheckEndTime TIME = '06:00:00';
第二步:执行校验查询
-- 检查是否存在重叠的服务时段 IF EXISTS ( SELECT 1 FROM #Calendar c WHERE -- 场景1:服务是同天时段(没跨天) (c.HourStart <= c.HourEnd AND ( -- 目标时段不跨天:服务星期和目标一致,且时间重叠 (@CheckStartDay = @CheckEndDay AND c.DayWeek = @CheckStartDay AND c.HourStart < @CheckEndTime AND c.HourEnd > @CheckStartTime) -- 目标时段跨天:服务在目标的星期区间内,且要么覆盖全天,要么和首尾时间重叠 OR (@CheckStartDay < @CheckEndDay AND c.DayWeek BETWEEN @CheckStartDay AND @CheckEndDay AND ( -- 服务在中间星期(比如目标是周一到周三,服务在周二),直接算重叠 (c.DayWeek > @CheckStartDay AND c.DayWeek < @CheckEndDay) -- 服务在起始星期,结束时间晚于目标开始时间 OR (c.DayWeek = @CheckStartDay AND c.HourEnd > @CheckStartTime) -- 服务在结束星期,开始时间早于目标结束时间 OR (c.DayWeek = @CheckEndDay AND c.HourStart < @CheckEndTime) )) )) OR -- 场景2:服务是跨天时段(比如19:00到07:00) (c.HourStart > c.HourEnd AND ( -- 服务跨天的区间和目标时段有重叠 ( -- 服务起始星期在目标区间内,或者跨到的下一个星期在目标区间内 (c.DayWeek BETWEEN @CheckStartDay AND @CheckEndDay) OR (c.DayWeek + 1 BETWEEN @CheckStartDay AND @CheckEndDay) -- 处理跨周末的情况(比如目标是周日到周一,DayWeek 7到1) OR (@CheckStartDay > @CheckEndDay AND (c.DayWeek >= @CheckStartDay OR c.DayWeek + 1 <= @CheckEndDay)) ) AND ( -- 服务起始星期和目标起始星期相同:服务开始时间早于目标结束时间 (c.DayWeek = @CheckStartDay AND c.HourStart < @CheckEndTime) -- 服务跨到的星期和目标结束星期相同:服务结束时间晚于目标开始时间 OR (c.DayWeek + 1 = @CheckEndDay AND c.HourEnd > @CheckStartTime) -- 服务完全覆盖目标的中间星期 OR (c.DayWeek > @CheckStartDay AND c.DayWeek + 1 < @CheckEndDay) ) )) ) BEGIN PRINT '❌ 该时段不可用,已有服务占用'; END ELSE BEGIN PRINT '✅ 该时段可用'; END
用你的示例数据测试
把你的示例表数据导入后,测试几个场景:
- 校验周一20:00到周二06:00:会检测到和
Make a Cake重叠,输出「不可用」 - 校验周二07:00到周二18:00:没有对应的服务时段,输出「可用」
- 校验周一18:00到周一20:00:和
Make a cookie(周一07-19)、Make a Cake(周一19-07)都重叠,输出「不可用」
小提示
- 如果你的
DayWeek规则是周日=1、周一=2这类,只需要调整参数的星期数值就行,逻辑不用改。 - 可以把这段逻辑封装成SQL函数,以后调用更方便。
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

