【发布时间】:2010-11-12 14:33:29
【问题描述】:
我有一个预订系统,我需要从数据库中选择任何可用的房间。基本设置是:
table: room
columns: id, maxGuests
table: roombooking
columns: id, startDate, endDate
table: roombooking_room:
columns: id, room_id, roombooking_id
我需要选择可以容纳请求的客人入住的房间,或者选择两个(或更多)房间来容纳客人(由 maxGuests 定义,显然首先使用最低/壁橱 maxGuests)
我可以遍历我的日期范围并使用这个 sql:
SELECT `id`
FROM `room`
WHERE `id` NOT IN
(
SELECT `roombooking_room`.`room_id`
FROM `roombooking_room`, `roombooking`
WHERE `roombooking`.`confirmed` =1
AND DATE(%s) BETWEEN `roombooking`.`startDate` AND `roombooking`.`endDate`
)
AND `room`.`maxGuests`>=%d
其中 %$1 是循环日期,%2d 是要预订的客人数量。但是如果客人数量超过任何房间可以容纳的人数,这将返回 false,并且必须有更快的方法来执行此操作而不是循环使用 php 并运行查询?
这类似于我想到的部分 sql:Getting Dates between a range of dates 但使用的是 Mysql
解决方案,基于 ircmaxwell 的回答:
$query = sprintf(
"SELECT `id`, `maxGuests`
FROM `room`
WHERE `id` NOT IN
(
SELECT `roombooking_room`.`room_id`
FROM `roombooking_room`
JOIN `roombooking` ON `roombooking_room`.`roombooking_id` = `roombooking`.`id`
WHERE `roombooking`.`confirmed` =1
AND (`roomBooking`.`startDate` > DATE(%s) OR `roomBooking`.`endDate` < DATE(%s))
)
AND `maxGuests` <= %d ORDER BY `maxGuests` DESC",
$endDate->toString('yyyy-MM-dd'), $startDate->toString('yyyy-MM-dd'), $noGuests);
$result = $db->query($query);
$result = $result->fetchAll();
$rooms = array();
$guests = 0;
foreach($result as $res) {
if($guests >= $noGuests) break;
$guests += (int)$res['maxGuests'];
$rooms[] = $res['id'];
}
【问题讨论】:
-
为什么有单独的 roombooking_room 表? table roombooking: id, room_id, startDate, endDate 不应该足够吗?
-
我认为执行您想要的操作所需的 SQL 实际上对于您想要实现的目标来说过于复杂。循环和使用 PHP 有什么问题?您可能还会发现,如果您使用纯 SQL 实现所需的结果,该解决方案实际上可能比使用 PHP 循环慢。但是,我对查看结果非常感兴趣,因为有时我发现自己会问类似的问题(PHP 与 SQL)。
-
@Axaryday 请参阅下面对答案的评论。这是必需的,因为一个预订期可能关联多个房间。也就是我住10个人,一个房间可以住6个人,所以我需要两个房间,但是在同一个订单下
-
我可能误解了这个问题。我的印象是您希望检查一系列任意日期(例如,8 月的每个周末),而不是“8 月 1 日至 14 日之间”。如果是这种情况,我们深表歉意。