Использование 2 таблиц для результатов

Я делаю систему бронирования для школьного проекта, но теперь я застрял.

У меня есть страница, где вы можете проверить, доступны ли номера для определенной категории номеров и даты.

Я знаю, что вы должны сделать внутреннее соединение. Я использовал Google, но я понятия не имею, как это сделать.

Это в моей базе данных отелей:

У меня есть стол для комнат:

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

Решение

Часть 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 Таблица).

Синтаксис и дополнительную информацию о подзапросах, пожалуйста, проверьте http://dev.mysql.com/doc/refman/5.1/en/subqueries.html.

Часть 2: Реализация PHP

Чтобы сделать этот шаг еще дальше и следовать своей бизнес-логике, можно сказать следующее:

Выберите те категории, в которых есть номера (по крайней мере, одна комната), не указанные в бронировании.

И это где вы можете реализовать INNER JOIN, Перевод нашей проблемы в MySQL — при условии, что у вас есть 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);

Если я не ошибаюсь, этот запрос должен запрашивать определенное имя категории, если хотя бы одна комната с таким идентификатором категории не указана в резервировании. Пожалуйста, проверьте, если это работает для вас, я не в такой среде, где я мог бы проверить это прямо сейчас.

РЕДАКТИРОВАТЬ: DISTINCT ключевое слово

Если запрос каким-либо образом возвращает заданный catagory несколько раз, пожалуйста, используйте DISTINCT ключевое слово:

SELECT DISTINCT catagory.name FROM catagory ...

Часть 3. Фильтрация результатов по дате начала и окончания

Для фильтрации по дате начала и окончания мы приходим к следующей проблеме:

Выберите те категории, в которых есть хотя бы одна комната, на которую нет ссылок
оговорки. Бронирование, которое выходит за рамки нашего времени (пример:
к моменту, когда следующий пользователь начинает
собственное бронирование) можно игнорировать, так как их номера свободны, поэтому они
больше не ограничивать наши возможности.

Переменные, используемые в следующем запросе:

$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 пункт.

1

Другие решения

Нет, вам также не нужно сохранять категорию в таблице бронирования, это будет избыточно.

Чтобы получить бронирование для этой категории и информацию о номере бронирования, вам понадобится запрос, подобный следующему:

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

По вопросам рекламы [email protected]