好的,所以我试图从DB中选择行,看看日历中是否有任何冲突,我遇到了另一个问题
这是我的代码
$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并且实际上超出了新事件,它也会允许它。因此,我需要上边界是动态的,因为if:calend&lt; (calTime + duration)然后选择行,否则使用:calend作为上边界。
我虽然对于我正在尝试的内容几乎是正确的但是这部分
( 1331388000 + ( duration - ( 1331388000 - calTime ) ) )
在某些情况下会减去负数,因此上边界要大得多,并且当它们不应该包含行时
答案 0 :(得分:2)
您似乎希望查看新条目是否与任何现有条目重叠。新条目由开始时间(在您的示例中为1331386200)和持续时间(1800,从评论推断,1331386200 + 1800 = 1331388000)指定。
SO上有许多问题(包括Determining whether two date ranges overlap)处理重叠时间段,但确定两个句点(由[s1, e1]
和[e2, s2]
表示的基本技术是否重叠很简单:
if (s1 < e2 && s2 < e1)
...the intervals overlap...
如果需要,您可以与<
vs <=
玩杂耍。当然,您可以根据需要为查询添加额外的条件。
将它应用到您的示例中,您似乎应该写这样的内容:
-- 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个此类行的列表)。