使用2个表格获得结果

时间:2014-10-03 15:44:39

标签: php mysql sql inner-join

我正在为学校项目制作预订系统,但现在我被卡住了。

我有一个页面,您可以在其中检查房间是否适用于特定的房间类别和日期

我知道你必须做一个内部联接。我使用谷歌,但我不知道如何做到这一点。

这是在我的酒店数据库中:

我有一张房间桌子:

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>

我希望有人可以帮助我!

提前谢谢你!

- 编辑

既然我正在查看预订表,那么将该类别存储在那里也不会更好吗?

2 个答案:

答案 0 :(得分:1)

第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

第2部分:PHP实现

为了更进一步,并遵循您的业务逻辑,可以说:

  

选择那些在预订中未引用的房间(至少一个房间)的类别

这是您可以实施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

第3部分:按开始日期和结束日期过滤结果

要按开始日期和结束日期进行过滤,我们会遇到以下问题:

  

选择至少有一个未引用的房间的类别   保留。超出我们时间范围的预订(例如:   在下一位用户开始使用时,预订已经过期   自己的预订)可以忽略,因为他们的房间是免费的,所以他们   不再限制我们的可能性。

下一个查询中使用的变量如下:

{{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'