我有一个包含开始和结束日期时间的表,我需要确定是否有任何重叠并且不确定最佳方式.
最初我正在考虑使用如下所示的嵌套游标,这确实有效,但是我正在检查彼此相同的记录两次并且我确定它不是非常有效.
例如:这个表会导致重叠.
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
Run Code Online (Sandbox Code Playgroud)
重叠是以下任何一种情况:
Start1 End1
---------------------------------------------------------------------------------
Start2 End2
Start2 End2
Start2 End2
并且不是以下任何一种情况:
Start1 End1
---------------------------------------------------------------------------------
Start2 End2
Start2 End2
如果你仔细观察,你会注意到Start2 < End1 AND End2 > Start1这种关系的定义,所以你可以减少你的表达.
其次,您可以将其置于WHERE光标的条件中,而不是循环遍历每一行并进行检查.
第三,既然你只是检查某些东西是否存在,你可以使用一个IF EXISTS子句而不是循环游标并检查.
最后,您可以使用INNER JOINon本身或者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
Run Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
2423 次 |
| 最近记录: |