选择行的SQL语句

时间:2012-03-10 22:13:05

标签: sql calendar

好的,所以我试图从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 ) ) )

在某些情况下会减去负数,因此上边界要大得多,并且当它们不应该包含行时

1 个答案:

答案 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个此类行的列表)。