我似乎对此SQL查询有问题:
SELECT * FROM appts
WHERE timeStart >='$timeStart'
AND timeEnd <='$timeEnd'
AND dayappt='$boatdate'
时间格式为军事时间。物流是租船可以在早上7点至下午1点至下午1点或上午9点至下午5点预订。如果在该范围内有appt,它应该返回appts,但事实证明它不一致。如果我选择上午9点直到下午1点,它将忽略从早上7点开始的应用程序,即使它在上午9点到下午1点重叠。如果我选择9到5,它将返回任何内容,即使它应该在早上7点到下午1点。如何创建包含从timeStart到timeEnd的整个范围的SQL语句,包括那些重叠的?
答案 0 :(得分:8)
Shahkalpesh回答了这个问题:
我认为你需要一个OR。
SELECT * FROM appts WHERE (timeStart >='$timeStart' OR timeEnd <='$timeEnd') AND dayappt='$boatdate'
我发表了一条评论,我认为这是错误的,给出了一对反例:
这是完全错误的 - @ShaneD是正确的。例如,这将在05:00和06:00之间选择预订,因为实际结束时间少于您询问的任何结束时间。由于同等原因,它还将从18:00开始接收租金。
在回应我的评论时,Shahkalpesh要求:
你能发布一个单独的回复数据&amp;具有预期输出的输入参数?
足够公平 - 是的。略有编辑,问题说:
逻辑是可以预订船只租赁
如果在该范围内有约会,它应该返回约会,但事实证明它是不一致的。如果我选择上午9点到下午1点,...
足够的背景。我们可以忽略约会的日期,只考虑时间。我假设有一种简单的方法可以将记录的时间限制为hh:mm格式;并非所有DBMS实际上都提供了这一点,但处理hh:mm:ss的扩展是微不足道的。
Appointments
Row timeStart timeEnd Note
1 07:00 13:00 First valid range
2 09:00 13:00 Second valid range
3 09:00 17:00 Third valid range
4 14:00 17:00 First plausibly valid range
5 05:00 06:00 First probably invalid range
6 18:00 22:30 Second probably invalid range
鉴于搜索约会范围与09:00 - 13:00重叠,Shahkalpesh的(简化)查询变为:
SELECT * FROM Appointments
WHERE (timeStart >= '09:00' OR timeEnd <= '13:00')
这将返回所有六行数据。但是,只有第1,2,3行与时间段09:00 - 13:00重叠。如果第1行,第2行和第3行是唯一有效的代表约会值,则Shahkalpesh的查询会生成正确的答案。但是,如果允许第4行(我认为合理有效),则不应返回。同样,不应返回第5行和第6行(如果存在)。 [实际上,对于表中的所有行假设 timeStart <= timeEnd
(并且没有NULL值可以搞乱),我们可以看到Shahkalpesh的查询将返回任意数据行对于09:00-13:00查询,因为行的开始时间大于09:00或结束时间小于13:00或两者。这相当于在WHERE子句中编写 1 = 1
或任何其他重言式。]
如果我们考虑ShaneD的查询(简化):
SELECT * FROM Appointments
WHERE timeStart <= '13:00' AND timeEnd >= '09:00'
我们看到它还选择第1,2和3行,但它拒绝第4行(因为timeStart&gt; '13:00'),5(因为timeEnd&lt; '09:00')和6(因为timeStart&gt; '13:00')。这个表达式是一个典型的例子,说明如何选择“重叠”,计数“满足”和“满足”(例如,参见“Allen's Interval Algebra”)重叠的行。更改'&gt; ='和'&lt; ='会更改计为重叠的间隔集。
答案 1 :(得分:6)
正确的检查如下:
SELECT * FROM appts
WHERE timeStart <='$timeEnd'
AND timeEnd >='$timeStart'
AND dayappt='$boatdate'
已经给出了其他很好的解释,但我会继续更新它,并提供另一种解释,说明我是如何自己想象的。大多数人都在寻找每个可能的重叠,考虑到两个时间段,他们试图考虑可以使约会重叠的开始和结束的每个组合。我认为这是因为两个时间段没有重叠,因为某些原因对我来说更容易。
说我正在检查的时间段是今天,我想找到今天不重叠的任何时间段。实际上只有两种情况,即时间段在今天之后开始(PeriodStart&gt; EndOfToday)或时间段在今天之前结束(PeriodEnd&lt; StartOfToday)。
鉴于我们有一个不重叠的简单测试:
(PeriodStart&gt; EndOfToday)或(PeriodEnd&lt; StartOfToday)
快速翻转,你有一个简单的重叠测试:
(PeriodStart&lt; = EndOfToday)AND(PeriodEnd&gt; = StartOfToday)
-Shane
答案 2 :(得分:0)
谢谢Shane,Shahkalpesh和Jonathan。
我实际上忽略了Shane“交换”变量的事实(我还在使用timeStart&lt; = $ timeStart,它应该是timeStart&lt; = $ timeEnd)。我按照Jonathan / Shane的建议运行修改后的声明并且它有效。正如乔纳森所指出的,我确实错过了一些我应该测试的时间范围。
现在有了Jonathan的解释,我现在可以更好地了解我的错误,这很有帮助。
答案 3 :(得分:-5)
我认为你需要一个OR。
SELECT * FROM appts
WHERE (timeStart >='$timeStart'
OR timeEnd <='$timeEnd')
AND dayappt='$boatdate'
假设每条记录仅关注特定日期。 租来的船只不会超过1天。