我正在为学校项目制作预订系统,但现在我被卡住了。
我有一个页面,您可以在其中检查房间是否适用于特定的房间类别和日期
我知道你必须做一个内部联接。我使用谷歌,但我不知道如何做到这一点。
这是在我的酒店数据库中:
我有一张房间桌子:
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>
我希望有人可以帮助我!
提前谢谢你!
- 编辑
既然我正在查看预订表,那么将该类别存储在那里也不会更好吗?
答案 0 :(得分:1)
良好做法首先将任务简化为简单的字:
选择那些未在任何预订条目中引用的房间,并且这些房间来自特定类别。
您实际上需要的不是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
rooms
SELECT roomNR FROM reservation
reservation
INNER JOIN
id
name
catagory
简单地说,SELECT catagory.name FROM catagory INNER JOIN rooms ON catagory.id=rooms.catagory WHERE rooms.roomNR NOT IN (SELECT roomNR FROM reservation);
表。)
有关子查询的语法和更多信息,请查看http://dev.mysql.com/doc/refman/5.1/en/subqueries.html。
为了更进一步,并遵循您的业务逻辑,可以说:
选择那些在预订中未引用的房间(至少一个房间)的类别
这是您可以实施DISTINCT
的地方。将我们的问题翻译成MySQL - 假设您有catagory
的{{1}}和DISTINCT
字段 - 我们有:
SELECT DISTINCT catagory.name FROM catagory ...
如果我没有弄错的话,如果在预订中至少有一个房间没有引用该catagory id,则此查询应查询给定的类别名称。请检查一下这是否适合您,我现在不在我可以测试的环境中。
编辑: $start_date = $_POST['startDate'];
$end_date = $_POST['endDate'];
关键字
如果查询以任何方式多次返回给定的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
要按开始日期和结束日期进行过滤,我们会遇到以下问题:
选择至少有一个未引用的房间的类别 保留。超出我们时间范围的预订(例如: 在下一位用户开始使用时,预订已经过期 自己的预订)可以忽略,因为他们的房间是免费的,所以他们 不再限制我们的可能性。
下一个查询中使用的变量如下:
{{1}}
使其成为SQL:
{{1}}
如您所见,我们在子查询中使用反逻辑。当我们检查某个房间是否已被保留(已在{{1}}中)时,我们会忽略那些不符合时间标准的预订:它已在下一个预订开始之前结束,或者在下一个预约结束之前开始。因此,它不会成为{{1}}子句的限制元素。
答案 1 :(得分:0)
不,您也不需要在预订表上保存类别,这将是多余的。
要获得该类别的预订,以及有关预订的房间信息,您需要这样的查询:
SELECT rooms.roomNR, rooms.category, rooms.picLocation,
res.reservationID, res.userID, res.start, res.end, res.price
FROM rooms
INNER JOIN reservations res ON rooms.roomNR = res.roomNR
WHERE rooms.category = 'your_category_selection'