我有一张包含开始和结束日期时间的表格,我需要确定是否有任何重叠并且不确定最佳方式。
最初我正在考虑使用如下所示的嵌套游标,但是我正在检查彼此相同的记录两次,我确信它不是很有效。
例如:此表会导致重叠。
id start end
-------------------------------------------------------
1 2009-10-22 10:19:00.000 2009-10-22 11:40:00.000
2 2009-10-22 10:31:00.000 2009-10-22 13:34:00.000
3 2009-10-22 16:31:00.000 2009-10-22 17:34:00.000
Declare @Start datetime, @End datetime, @OtherStart datetime, @OtherEnd datetime, @id int, @endCheck bit
Set @endCheck = 0
DECLARE Cur1 CURSOR FOR
select id, start, end from table1
OPEN Cur1
FETCH NEXT FROM Cur1 INTO @id, @Start, @End
WHILE @@FETCH_STATUS = 0 AND @endCheck = 0
BEGIN
-- Get a cursor on all the other records
DECLARE Cur2 CURSOR FOR
select start, end from table1
and id != @id AND start < @end
OPEN Cur2
FETCH NEXT FROM Cur2 INTO @OtherStart, @OtherEnd
WHILE @@FETCH_STATUS = 0 AND @endCheck = 0
BEGIN
if ( @Start > @OtherStart AND @Start < @OtherEnd OR
@End > @OtherStart AND @End < @OtherEnd )
or
( @OtherStart > @Start AND @OtherStart < @End OR
@OtherEnd > @Start AND @OtherEnd < @End )
BEGIN
SET @endCheck = 1
END
FETCH NEXT FROM Cur2 INTO @OtherStart, @OtherEnd
END
CLOSE Cur2
DEALLOCATE Cur2
FETCH NEXT FROM Cur1 INTO @id, @Start, @End
END
CLOSE Cur1
DEALLOCATE Cur1
答案 0 :(得分:8)
重叠是以下任何一种情况:
Start1 End1 --------------------------------------------------------------------------------- Start2 End2 Start2 End2 Start2 End2
并且不是以下任何一种情况:
Start1 End1 --------------------------------------------------------------------------------- Start2 End2 Start2 End2
如果你仔细观察,你会发现Start2 < End1 AND End2 > Start1
定义了这种关系,所以你可以将你的表达减少到这个。
其次,您可以将其置于光标的WHERE
条件下,而不是遍历每一行并进行检查。
第三,既然你只是检查是否存在某种东西,你可以使用IF EXISTS
子句而不是循环游标并检查。
最后,您可以使用INNER JOIN
本身或WHERE EXISTS
将这一切缩减为单个查询,具体取决于您希望最终输出的外观。要获得表格中的所有重叠,您可以尝试以下内容(t2.id > t1.id
只能获得每次重叠一次):
SELECT t1.id, t2.id
FROM MyTable t1
INNER JOIN MyTable t2 ON t2.id > t1.id
AND t2.start < t1.end AND t2.end > t1.start
答案 1 :(得分:3)
我不确定你想要的结果输出是什么样的,但你可以试试这个:
SELECT
TD1.*
FROM
table1 TD1
JOIN table1 TD2 ON
TD1.start BETWEEN TD2.start AND TD2.[end]
AND TD1.id != TD2.id
答案 2 :(得分:1)
您可以尝试此查询。实质上,如果开始时间出现在任何其他记录的开始和结束时间之间,它会从table1中选择id。
这将获得所有“跳枪”并在另一个条目结束前开始的条目。
select id
from table1 f1
where exists(
select 1
from table1 f2
where f1.id <> f2.id
AND f1.start >= f2.start
AND f1.start <= f2.[end]
)
答案 3 :(得分:1)
我认为您需要做的就是将结束日期与下一个开始日期进行比较,以找出重叠的内容。这可能会返回重复项,如果您只想要每个重叠的1个副本,则可能需要抛出DISTINCT。
SELECT a.* FROM Table1 a
INNER JOIN Table1 b
ON a.End > b.Start AND a.id <> b.id