Упростите запрос от выбора в выборе, чтобы использовать соединение - PullRequest
1 голос
/ 01 апреля 2020

У меня есть две таблицы, подобные этой:

Room
-----------------
id

и

Reservation
-----------------
id
room_id
check_in
check_out

Я стремлюсь получить все номера, которые не забронированы, в течение указанного периода c check_in и check_out .

Пока мне удалось построить запрос следующим образом:

select * from room
where room.id not in (
select room2.id from room as room2
inner join reservation r on room2.id = r.room_id
where r.check_in > '2020-04-19' and r.check_out < '2020-04-25');

Но я считаю, что должен быть более оптимальный способ сделать это, используя левое соединение.

Как создать эквивалентный запрос, используя только объединения?

Ответы [ 3 ]

2 голосов
/ 01 апреля 2020

Вы можете сделать это с LEFT JOIN, где вы отфильтровываете все подходящие строки:

select rm.* 
from room rm left join reservation rs
on rs.room_id = rm.room_id and rs.check_in > '2020-04-19' and rs.check_out < '2020-04-25'
where rs.room_id is null

Как видите, все условия должны быть помещены в предложение ON.

1 голос
/ 01 апреля 2020

Ваш not in подход не нуждается в join и мог бы быть выражен таким образом. Используйте это, только если вы уверены, что у вас нет нулевых значений для соответствующих столбцов в таблице бронирования.

select * 
from room
where id not in (select room_id 
                  from reservation
                  where check_in > '2020-04-19' and check_out < '2020-04-25');

Если вы настаиваете на использовании join

select t1.*
from room t1
inner join (select distinct room_id 
            from reservation 
            where check_in <= '2020-04-19' and check_out >= '2020-04-25') t2     
on t1.id=t2.room_id
1 голос
/ 01 апреля 2020

Я бы предложил not exists:

select r.*
from room r
where not exists (select 1
                  from reservation res
                  where r.id = res.room_id and
                        res.check_in > '2020-04-19' and
                        res.check_out < '2020-04-25'
                 );

Обратите внимание, что нет необходимости в join в подзапросе (ни в вашей версии, но я настоятельно не рекомендую not in с подзапросами из-за обработка значений null).

С точки зрения производительности это должно быть лучше или сопоставимо с left join в большинстве баз данных. Можно воспользоваться индексом на reservations(room_id, check_in, check_out).

...