2015-09-14 113 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