我有一张表,其中包含重叠时段的记录。
例如:日历(Id int,StartDate datetime,EndDate datetime,EventTitle nvarchar(100),...)
记录就像
- 01/20/2011 08:15 AM --- 01/20/2011 08:40 AM
- 01/20/2011 08:20 AM --- 01/20/2011 08:55 AM
- 01/20/2011 12:30 PM --- 01/20/2011 01:15 PM
- 01/20/2011 02:00 PM --- 01/20/2011 02:45 PM
- 01/20/2011 02:15 PM --- 01/20/2011 02:30 PM
- 01/21/2011 12:30 PM --- 01/21/2011 01:15 PM
- .......
- .......
醇>
该表代表一个人的活动时间表
我想把重叠的插槽聚集在一起给出:
- 01/20/2011 08:15 AM --- 01/20/2011 08:55 AM
- 01/20/2011 12:30 PM --- 01/20/2011 01:15 PM
- 01/20/2011 02:00 PM --- 01/20/2011 02:45 PM
- 01/21/2011 12:30 PM --- 01/21/2011 01:15 PM
- ...
- ...
醇>
我遇到问题的这一部分...(我删除了我粘贴在这里的代码,因为它看起来很糟糕。我第一次使用stackoverflow。)
我的部分实际要求是在两个给定日期之间找到一个时间段[t](比方说25分钟),我可以将其纳入时间表。 [t]必须在任何一天的上午8:00到下午05:00之间找到。
答案 0 :(得分:2)
这是一个有趣的问题。
对于指定日期,我们可以考虑重叠(我输入了您的所有日期时间,但是对于2011年1月1日):
SELECT dt1.StartTime AS StartOverlap,
CASE
WHEN dt1.EndTime > dt2.EndTime THEN dt1.EndTime
ELSE dt2.EndTime
END AS EndOverlap
FROM datetimetest dt1, datetimetest dt2
WHERE dt2.StartTime > dt1.StartTime
AND dt2.StartTime < dt1.EndTime
这给了我:
StartOverlap EndOverlap
01/01/2011 08:15:00 01/01/2011 08:55:00
01/01/2011 14:00:00 01/01/2011 14:45:00
太好了,我们现在知道我们不能使用这种重叠的开始和结束时间。
我们如何得到其他没有重叠的时间?
我会查看重叠范围内的所有时间段,然后选择不在该日期范围内的ID:
SELECT id
FROM (SELECT dt1.StartTime AS StartOverlap,
CASE
WHEN dt1.EndTime > dt2.EndTime THEN dt1.EndTime
ELSE dt2.EndTime
END AS EndOverlap
FROM datetimetest dt1, datetimetest dt2
WHERE dt2.StartTime > dt1.StartTime
AND dt2.StartTime < dt1.EndTime
) AS Overlaps, datetimetest dtt
WHERE dtt.StartTime >= Overlaps.StartOverlap
AND dtt.EndTime <= Overlaps.EndOverlap
这为我提供了重叠中所有ID的列表。然后我只选择不在重叠中的所有条目:
SELECT StartTime, EndTime FROM datetimetest
WHERE id NOT IN(
SELECT id
FROM (SELECT dt1.StartTime AS StartOverlap,
CASE
WHEN dt1.EndTime > dt2.EndTime THEN dt1.EndTime
ELSE dt2.EndTime
END AS EndOverlap
FROM datetimetest dt1, datetimetest dt2
WHERE dt2.StartTime > dt1.StartTime
AND dt2.StartTime < dt1.EndTime
) AS Overlaps, datetimetest dtt
WHERE dtt.StartTime >= Overlaps.StartOverlap
AND dtt.EndTime <= Overlaps.EndOverlap)
给我:
StartTime EndTime
01/01/2011 12:30:00 01/01/2011 13:15:00
然后,我可以将两个查询合并在一起,为我提供所有使用时间段的列表。
由于我们实际上正在交叉加入同一个表,因此我会在每个查询中添加一个附加子句,以将日期约束为单个日期。