我正在为学校项目制作预订系统,但现在卡住了。
我有一个页面,您可以在其中查看特定房间类别和日期的房间是否可用
我知道您必须进行内部联接。我用过谷歌,但我不知道如何去做。
这是在我的酒店数据库中:
我有一张房间表:
TABLE `rooms` ( `roomNR` int(11) NOT NULL, `catagory` varchar(11) DEFAULT NULL, `picLocation` varchar(50) DEFAULT NULL, PRIMARY KEY (`roomNR`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
我有一个预订表,其中存储了所有预订。
TABLE `reservation` (
`reservationID` int(11) unsigned NOT NULL AUTO_INCREMENT,
`userID` int(11) NOT NULL,
`roomNR` int(11) NOT NULL,
`start` date NOT NULL,
`end` date NOT NULL,
`price` float NOT NULL,
PRIMARY KEY (`reservationID`),
UNIQUE KEY `userID` (`userID`),
UNIQUE KEY `roomNR` (`roomNR`),
CONSTRAINT `reservation_ibfk_1` FOREIGN KEY (`roomNR`) REFERENCES `rooms` (`roomNR`),
CONSTRAINT `reservation_ibfk_2` FOREIGN KEY (`userID`) REFERENCES `users` (`userID`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
这是我使用的表格:
<form action="" method="GET">
<div>
<label for="StartDate">From</label>
<input type="input" name="startDate" id="startDate" readonly=""> <label for="EndDate">Till</label> <input readonly="" type="input" name="endDate" id="endDate">
<label for="Catagory">Catagory:</label>
<select name="Catagory" id="Catagory">
<?php
$catagorys = DB::Getinstance()->query('SELECT * FROM catagory');
if ($catagorys->count()) {
foreach($catagorys->results() as $catagory){?>
<option value="<?php echo $catagory->name; ?>"><?php echo $catagory->name; ?></option>
<?php }
}
?>
</select> <input type="submit" value="get available rooms" class="btn btn-default">
</div>
</form>
我希望有人能帮助我!
提前致谢!
-- 编辑
既然我正在查看预订表,那么将目录也存储在那里不是更好吗?
最佳答案
第 1 部分:未预订的房间
首先将任务简化为简单的单词是一个好的做法:
Select those rooms, which are not referred to in any reservation entry, and are from a given category.
您实际上在这里需要的不是INNER JOIN
。至少不适合这部分任务。 INNER JOIN
稍后将用于与 catagory
进行“链接”。
在这里使用 INNER JOIN
可以轻松选择已经保留的房间:SELECT rooms.roomNR FROM rooms INNER JOIN reservation ON rooms.roomNR=reservation.roomNR WHERE catagory=$category_id
.当然,您可以在 PHP 中处理此信息并使用它来非常有效地选择表中的剩余行,但还有更好的方法。
您需要一个子查询。
SELECT roomNR FROM `rooms` WHERE catagory=$category_id AND roomNR NOT IN (SELECT roomNR FROM `reservation`)
MySQL(或一般的 SQL)的一个幸运特性是,语言语法尽可能地类似于英语书面语言。 查询解释:我们SELECT
那些房间
的roomNR
不在SELECT roomNR FROM reservation
结果(或者,简单地说,reservation
表)。
有关子查询的语法和更多信息,请查看 http://dev.mysql.com/doc/refman/5.1/en/subqueries.html .
第 2 部分:PHP 实现
为了更进一步,并遵循您的业务逻辑,可以说以下内容:
Select those categories, that have rooms (at least one room) not referenced in reservation
这是您可以实现 INNER JOIN
的地方。将我们的问题转化为 MySQL - 假设你有 catagory
的 id
和 name
字段 - 我们有:
SELECT catagory.name FROM catagory INNER JOIN rooms ON catagory.id=rooms.catagory WHERE rooms.roomNR NOT IN (SELECT roomNR FROM reservation);
如果我没记错的话,如果至少有一个房间的类别 ID 未在预订中引用,则此查询应该查询给定的类别名称。请回来检查这是否适合您,我现在不在可以测试它的环境中。
编辑 DISTINCT
关键字
如果查询以任何方式多次返回给定的 catagory
,请使用 DISTINCT
关键字:
SELECT DISTINCT catagory.name FROM catagory ...
第 3 部分:按开始和结束日期过滤结果
要按开始日期和结束日期进行过滤,我们会遇到以下问题:
Select those categories, that have at least one room not referenced in reservations. Reservations that are outside our time scope (example: reservation has already expired by the time the next user begins their own reservation) can be ignored, since their rooms are free, so they no longer limit our possibilities.
下一个查询中使用的变量是这些:
$start_date = $_POST['startDate'];
$end_date = $_POST['endDate'];
将其转换为 SQL:
SELECT catagory.name FROM catagory INNER JOIN rooms ON catagory.id=rooms.catagory WHERE rooms.roomNR NOT IN (SELECT roomNR FROM reservation WHERE end<$start_date OR start>$end_date);
如您所见,我们在子查询中使用了逆逻辑。当我们检查给定房间是否已被预订时(已经在 reservation
中),我们忽略那些不符合时间标准的预订:它在下一次预订开始之前结束,或者在下一次预订之前开始结束。因此,它不会成为 NOT IN
子句的限制元素。
关于php - 使用 2 个表格获取结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26182279/