2012-03-10 120 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