2015-09-14 61 views
1

有没有一种方法可以测试一个表格中两个属性给出的区间是否与另一个属于“硬编码”的区域相交?假设我们有一张桌子相交两个区间

a | b 
2 | 3 
4 | 6 
1 | 2 

其中两个属性标记一个区间。现在我想要得到所有相交的间隔,例如{3, 5}(现在我们称这两个数字较低(l) - 较高(u))。这应该导致{{3}, {4, 5}}

我已经想到了办法建立一个巨大的SQL查询,检查为以下四种情况要返回的每一行:

a >= l && b <= u // attribute-given interval completely enclosed by bounds 
a <= l && b <= u // attribute-given interval falls out to "the left" 
a >= l && b >= u // attribute-given interval falls out to "the right" 
a <= l && b >= u // bounds are completely enclosed by attribute-given interval 

但是我使用任何内建想知道,如果看到一只聪明的做法在功能二中执行这样的交集。

我为此使用Oracle 11g。

回答

2

假设你的时间间隔对被有序(即a <= b所有行),你可以用这个公式来检查,如果时间间隔相交:

SELECT * 
FROM MyIntervals 
WHERE LEAST(b, u) >= GREATEST(a, l) 

的想法是,看看是否右侧的小两个间隔中的最大值大于左侧中的最大值。

上述公式将返回间隔重叠的所有行,触摸时为。如果您不想触摸间隔,请使用>来代替>=

+0

哇,这是很快的速度......不得不验证它,但对于我的第一次测试,它似乎相当不错。我怎样才能解决这个问题:上限和下限都被修复了,以致于在这些界限上产生了间隔?为了我的意思,请参阅我的“{{3},{4,5}}”的例子。 – HimBromBeere

+0

@HimBromBeere当区间相交时,交点可以作为一对'(GREATEST(a,l),LEAST(b,u))'找到。对于你的'(3,5)'和匹配行'(4,6)'的例子,'GREATEST'将返回'4',并且'LEAST'将返回'5',给你的'(4,5)结果。对于触摸区间'(2,3)','LEAST'和'GREATEST'都会返回'3'。 – dasblinkenlight

+0

我认为'{3,5}'也会从第一个时间间隔('{2,3}')匹配'3'。 – HimBromBeere

0

使用此代码:

select * 
    from MyIntervals MI 
where MI.A <= U 
    and L <= MI.B 

这将让一切准备您的间隔交叠前缘,或者你的目标区间后缘,或者您的间隔完全包含,或完全包含您的目标区间。

这适用于A < = B和L < = U,因为当两个范围以任何方式重叠时,每个范围的开始将总是小于另一个范围的结束。如果它们不重叠,那么只有两种情况他们不会,一种是A> U,另一种是可以重写为L> B的地方。 (A> U)| (L> B),并且当NOT((A> U)|(L> B))时它们重叠。应用De Morgan's Laws

NOT((A > U) | (L > B)) 
= NOT(A > U) & NOT(L > B) 
= (A <= U) & (L <= B) 
+0

这将只从表中完全包含给定的那些间隔中选择。我需要的还有那些完全或部分包含在给定范围内的。 – HimBromBeere

+0

仔细看看谓词。假设A总是<= B,并且L总是<= U,它将得到全部四个重叠排列 – Sentinel