我对一些 MYSQL 有一点问题。
我需要能够检查一段时间是否已经在度假屋预订了一段时间。
我的数据库使用 DATETIME 字段,并按如下方式设置:
数据库图像链接,因为我的代表很少
我有一个这样的查询:
SELECT * FROM `caravanavail1`
WHERE (`checkIn` BETWEEN '2014-01-07 14:00:00' AND '2014-01-08 10:00:00')
OR (`checkOut` BETWEEN '2014-01-07 14:00:00' AND '2014-01-08 10:00:00')
我总是会传递两个日期,但有时日期可能会在很多方面发生冲突:
- 入住可能在另一个假期中间,退房可能不会。
- 退房可能在另一个假期中间,而入住可能不会。
- 他们可能与另一个假期的日期相同。
- 我提供的入住和退房日期可能都在另一个预订中。
我已经为此挠头几天了,任何人都可以帮助我修复上面的SQL代码(我更喜欢一个查询,而不是两个查询)来返回我需要的东西吗?
|________| // date to book
|______| // condition 1
|______| // condition 2
|____| // condition 3
|________________| // condition 4
如果这 4 个条件中的任何一个导致连续,这意味着预订无法完成。
$in = '2014-01-07 14:00:00';
$out = '2014-01-08 10:00:00';
SELECT *
FROM `caravanavail1`
WHERE
(`checkIn` <= '$in' AND `checkOut` <= '$out') // condition 1
OR
(`checkIn` >= '$in' AND `checkOut` >= '$out') // condition 2
OR
(`checkIn` >= '$in' AND `checkOut` <= '$out') // condition 3
OR
(`checkIn` <= '$in' AND `checkOut` >= '$out') // condition 4
正如Marc B还指出的那样,这可以进一步简化:条件的所有入住时间都在您要预订的退房时间之前,条件的所有退房时间都在您要预订的入住时间之后
归结为:
SELECT *
FROM `caravanavail1`
WHERE
(`checkIn` < '$out' AND `checkOut` > '$in')
有时它有助于可视化:)
考虑这个图。其中x
和y
是相关签入/签出时间,p
和q
是数据库中的签入/签出时间。这两个日期范围可以通过多种方式重叠:
x y
p q // complete non-overlap, no conflict
p q // partial overlap, conflict
p q // partial overlap, conflict
p q // partial overlap, conflict
p q // complete non overlap, no conflict
如果你绘制出逻辑,你会发现
if (q >= x) && (p <= y) {
... there is a conflict
}
彪生你的基地。
为了达到何时存在重叠范围的条件,更容易考虑没有重叠的地方,然后反转条件。如果一个范围完全在另一个范围之前或之后,则两个范围不会重叠。
在SQL中,这转换为退房日期在给定的签入日期之前,或者签入日期在给定的退房日期之后:
SELECT * FROM `caravanavail1` WHERE NOT (checkOut <= '$in' OR checkIn >= '$out')
您可以将其简化为:
SELECT * FROM `caravanavail1` WHERE checkOut > '$in' AND checkIn < '$out'