2012-03-10 119 views
0

好了,所以我想選擇DB行,看是否有在日曆中的任何衝突,我所遇到的另一個問題SQL語句選擇行

這裏是我的代碼

$query3 = $dbh->prepare("SELECT * FROM calendar_" . $companyID . " WHERE (calTime+duration) > :calstart AND (calTime+duration) <= (:calend + (duration-(:calend-calTime))) AND agentID = :agentID ORDER BY calTime ASC"); 
$query3->bindParam(':calstart', $time); 
$calend = $time + $duration; 
$query3->bindParam(':calend', $calend); 

這看起來是一個像這樣更具可讀性SQL

SELECT * FROM calendar_01 WHERE (calTime + duration) > 1331386200 
    AND (calTime + duration) <= (1331388000 + (duration - (1331388000 - calTime))) 
    AND agentID =1 
    ORDER BY calTime ASC 
    LIMIT 0 , 30 

下邊界明顯工作正常但與上邊界我有問題,即如果一個事件的持續時間是7200 2小時,有人試圖進入一個新的事件,即只有1800的長度,並在第一個事件發生後1800開始允許它,即使已經輸入的事件長度爲7200並且事實上會超出新事件。因此,我需要上邊界是動態的,因爲如果:calend <(calTime + duration)然後選擇行,否則使用:calend作爲上邊界。

我,雖然我幾乎是正確的什麼我卻在嘗試此部分

(1331388000 + (duration - (1331388000 - calTime))) 

結束了在某些情況下減減,因此上界是非常大的,包括對行的時候,他們不應該

+0

對不起,但你的問題是什麼? – Ben 2012-03-11 00:15:08

回答

2

看來您正在查看新條目是否與任何現有條目重疊。新條目由開始時間(在您的示例中爲1331386200)和持續時間(從評論1331386200 + 1800 = 1331388000推斷出1800)指定。

有許多對SO(包括Determining whether two date ranges overlap),該處理在重疊時間段的問題,但是,用於確定兩個時期,通過[s1, e1][e2, s2]重疊表示是否是簡單的基本技術:

if (s1 < e2 && s2 < e1) 
    ...the intervals overlap... 

您如果需要,可以與<<=玩弄。當然,您可以根據需要爲查詢添加額外的條件。

應用,爲您的例子,看來,你應該寫這樣的事:

-- s1 == calTime 
-- e1 == calTime + duration 
-- s2 == 1331386200 
-- e2 == 1331388000 

SELECT * 
FROM calendar_01 
WHERE calTime < 1331388000   -- s1 < e2 
    AND 1331386200 < (calTime + duration) -- s2 < e1 
    AND agentID = 1      -- other criteria 
ORDER BY calTime ASC 
LIMIT 0 , 30 

如果返回任何數據,再有就是新的數據和一個或多個現有行之間的衝突數據(該語句將返回最多30個這樣的行的列表)。

+0

非常感謝您再次完美工作,當通常有一個非常簡單的答案時,卡住思考的東西! – Ash 2012-03-11 11:40:25