Я бы рассматривал в качестве основой единицы бронирования не квартиру, а кровати.
SLOTS — принадлежность кровати квартире
slot_id | apartment_id | ( price и прочее свойства кровати... )
RESERVATIONS — резервирование слотов — ссылка на бронирование. В одном бронировании может быть несколько слотов (кроватей), тогда будет несколько строчек на одно бронирование (с одинаковым booking_id)
slot_id | booking_id
BOOKINGS — бронирования
booking_id | user_id | start_date | end_date | ( discount и прочее, что хотите... )
Количество гостей хранить избыточно, т.к. число строк в RESERVATIONS с данным booking_id и будет числом гостей.
Ну и дальше всякое информационное наполнение по пользователям и квартирам:
USERS
user_id | name | email | ...
APARTMENTS
apartment_id | address | ...
Общее количество слотов в квартире, опять-таки, хранить не надо, т.к. оно определяется количеством строк в таблице SLOTS для данной apartment_id.
Чтобы определить количество забронированных слотов на любую дату $checking_date в квартире $apartment_id надо осуществлять довольно сложный запрос:
SELECT COUNT( slot_id ) FROM SLOTS WHERE
apartment_id = $apartment_id AND
slot_id IN (
SELECT slot_id FROM RESERVATIONS WHERE
booking_id IN (
SELECT booking_id FROM BOOKINGS WHERE
start_date <= $checking_date AND end_date > $checking_date
)
)
Поэтому имеет смысл вычислять и собирать эти данные в отдельную таблицу, где на каждую дату будут храниться данные о забронированных слотах в каждой квартире, которые обновлять при каждом бронировании, его изменении или отмене.
OCCUPIED
date | apartment_id | n_occupied | n_available