SQL становится доступным между датами - PullRequest
0 голосов
/ 04 июля 2018

У меня есть две таблицы. Это выглядит так

Настольные машины

+====+=========+=============+
| ID | mark    | description |
+====+=========+=============+
| 1  | 1234 AB | Volvo V70   |
+----+---------+-------------+
| 2  | 4567 CD | VW GOLF     |
+====+=========+=============+

Заказ столиков

+====+========+============+============+
| ID | car_id | date_from  | date_to    |
+====+========+============+============+
| 1  | 2      | 2018/01/01 | 2018/02/01 |
+----+--------+------------+------------+
| 2  | 1      | 2018/03/01 | 2018/04/01 |
+----+--------+------------+------------+
| 3  | 1      | 2018/05/01 | 2018/06/01 |
+----+--------+------------+------------+
| 4  | 2      | 2018/07/01 | 2018/08/01 |
+====+========+============+============+

Мне нужен SQL-запрос, который возвращает все доступные автомобили за определенный период времени. Это значит: если я задаю параметры запроса 2018/01/13 и 2018/01/17, я получу автомобиль № 2 только потому, что другой недоступен.

Вот моя первая идея:

select c.id, 
       c.mark
from cars c
join bookings b on c.id = b.car_id
where to_date('2017/01/13', 'yyyy/mm/dd') not between b.date_from and b.date_to
  and to_date('2017/01/17', 'yyyy/mm/dd') not between b.date_from and b.date_to;

Это дает мне больше строк, чем я ожидаю.

Каким должен быть правильный запрос для достижения этой цели?

Редактировать: Я на Oracle 12c

Ответы [ 3 ]

0 голосов
/ 04 июля 2018

Это может сработать

SELECT DISTINCT c.id,
       c.mark
FROM cars c
JOIN bookings b ON c.id = b.car_id
WHERE (to_date('2017/01/13', 'yyyy/mm/dd') < b.date_from AND to_date('2017/01/17', 'yyyy/mm/dd') < b.date_to)
  OR (to_date('2017/01/13', 'yyyy/mm/dd') < b.date_from AND to_date('2017/01/17', 'yyyy/mm/dd') < b.date_to)
0 голосов
/ 04 июля 2018

Если я правильно понял это требование, вы ищете автомобили, которые не имеют заказов на указанный диапазон дат. Поэтому вам не следует присоединяться к таблице bookings, потому что это даст вам автомобили с уже зарегистрированными бронированиями на другие периоды. Вы ищете автомобили, где нет бронирования, поэтому:

with cars (id, mark, description) as
       ( select 1, '1234 AB', 'Volvo V70' from dual union all
         select 2, '4567 CD', 'VW Golf' from dual )
   , bookings (id, car_id, date_from, date_to ) as
       ( select 1, 2, date '2018-01-01', date '2018-02-01' from dual union all
         select 2, 1, date '2018-03-01', date '2018-04-01' from dual union all
         select 3, 1, date '2018-05-01', date '2018-06-01' from dual union all
         select 4, 2, date '2018-07-01', date '2018-08-01' from dual )
select c.*
from   cars c
where  not exists
       ( select 1 from bookings b
         where  b.car_id = c.id
         and    (   date '2018-01-13' between b.date_from and b.date_to
                 or date '2018-01-17' between b.date_from and b.date_to )
       );

Результат:

        ID MARK    DESCRIPTION
---------- ------- -----------
         1 1234 AB Volvo V70

Автомобиль 1 доступен, потому что он забронирован только на март и май, а Golf забронирован на январь и июль.

0 голосов
/ 04 июля 2018

Вы пробовали это:

DECLARE @dateToCheck datetime

SELECT cars.id, cars.mark, cars.description FROM cars
INNER JOIN bookings ON bookings.car_id = car.id
WHERE @dateToCheck BETWEEN booking.date_from AND booking.date_to
...