相交两个区间

时间:2015-09-14 13:57:03

标签: sql oracle

有没有办法可以测试一个表中两个属性给出的间隔是否是另一个“硬编码”的?假设我们有一张桌子

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 个答案:

答案 0 :(得分:2)

假设您的区间对是有序(即所有行都是a <= b),您可以使用此公式来检查区间是否相交:

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

我们的想法是看两个间隔中较小的右边是否大于左边的最大边。

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

答案 1 :(得分:0)

使用此代码:

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

这将获得您的间隔与前缘或目标间隔的后缘重叠,或者您的间隔完全包含或者完全包含在目标间隔内的所有可能性。

当A&lt; = B且L&lt; = U时,这是有效的,因为当两个范围以任何方式重叠时,每个范围的开始总是小于另一个范围的结束。如果他们不重叠,那么只有两种情况他们不会,其中一种情况是A&gt; U和另一个是B&lt; L可以重写为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)