помощь в формировании запроса MySQL для поиска свободных (доступных) мест / ресурсов для заданного диапазона дат - PullRequest
2 голосов
/ 12 января 2010

У меня есть такие таблицы и данные:

venues table contains : id<br/>
+----+---------+
| id | name    |
+----+---------+
|  1 | venue 1 |
|  2 | venue 2 |
---------------

event_dates : id, event_id, event_from_datetime, event_to_datetime, venue_id
+----+----------+---------------------+---------------------+----------+
| id | event_id | event_from_datetime | event_to_datetime   | venue_id |
+----+----------+---------------------+---------------------+----------+
|  1 |        1 | 2009-12-05 00:00:00 | 2009-12-07 00:00:00 |        1 |
|  2 |        1 | 2009-12-09 00:00:00 | 2009-12-12 00:00:00 |        1 |
|  3 |        1 | 2009-12-15 00:00:00 | 2009-12-20 00:00:00 |        2 |
+----+----------+---------------------+---------------------+----------+

Это мое требование: я хочу места, которые будут свободны в 2009-12-06 00:00:00 т.е.

Я должен получить

| venue_id |

| 2 |

В настоящее время у меня следующий запрос,

select ven.id , evtdt.event_from_datetime, evtdt.event_to_datetime 
from venues ven 
left join event_dates evtdt 
on (ven.id=evtdt.venue_id) 
where evtdt.venue_id is null 
or not ('2009-12-06 00:00:00' between evtdt.event_from_datetime 
                                  and evtdt.event_to_datetime);
+----+---------------------+---------------------+
| id | event_from_datetime | event_to_datetime   |
+----+---------------------+---------------------+
|  1 | 2009-12-09 00:00:00 | 2009-12-12 00:00:00 |
|  2 | 2009-12-15 00:00:00 | 2009-12-20 00:00:00 |
|  3 | NULL                | NULL                |
|  5 | NULL                | NULL                |
+----+---------------------+---------------------+

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

Заранее спасибо.

Ответы [ 3 ]

2 голосов
/ 12 января 2010
SELECT  *
FROM    venue v
WHERE   NOT EXISTS
        (
        SELECT  NULL
        FROM    event_dates ed
        WHERE   ed.venue_id = v.id
                AND '2009-12-06 00:00:00' BETWEEN ed.event_from_datetime AND ed.event_to_datetime
        )
1 голос
/ 12 января 2010
or not ('2009-12-06 00:00:00' between evtdt.event_from_datetime 
                              and evtdt.event_to_datetime);

12/6/2009 равно в период с 12/5/09 по 12/7/09 ... поэтому исключение venue_id 1 ... из чего вы пытаетесь извлечь данные точно?

Запрос на объединение, который вы создали, говорит: возьмите таблицу мест и для каждой строки, для которой есть соответствующий venue_id, сделайте копию строки таблицы мест и добавьте соответствующую строку. Так что, если вы только что сделали:

select * 
  from venues ven 
  left join event_dates evtdt 
  on (ven.id=evtdt.venue_id);

Это даст:

+----+---------+------+----------+---------------------+---------------------+----------+
| id | name    | id   | event_id | event_from_datetime | event_to_datetime   | venue_id |
+----+---------+------+----------+---------------------+---------------------+----------+
|  1 | venue 1 |    1 |        1 | 2009-12-05 00:00:00 | 2009-12-07 00:00:00 |        1 |
|  1 | venue 1 |    2 |        1 | 2009-12-09 00:00:00 | 2009-12-12 00:00:00 |        1 |
|  2 | venue 2 |    3 |        1 | 2009-12-15 00:00:00 | 2009-12-20 00:00:00 |        2 |
+----+---------+------+----------+---------------------+---------------------+----------+

Если вы затем добавили свое условие, в котором указывается, что интересующая дата не находится между датой и датой события, запрос выглядит следующим образом:

select * 
  from venues ven 
  left join event_dates evtdt 
  on (ven.id=evtdt.venue_id) 
  where not ('2009-12-06' between evtdt.event_from_datetime and evtdt.event_to_datetime)

Что дает результат:

+----+---------+------+----------+---------------------+---------------------+----------+
| id | name    | id   | event_id | event_from_datetime | event_to_datetime   | venue_id |
+----+---------+------+----------+---------------------+---------------------+----------+
|  1 | venue 1 |    2 |        1 | 2009-12-09 00:00:00 | 2009-12-12 00:00:00 |        1 |
|  2 | venue 2 |    3 |        1 | 2009-12-15 00:00:00 | 2009-12-20 00:00:00 |        2 |
+----+---------+------+----------+---------------------+---------------------+----------+

Это мои реальные экспериментальные результаты с вашими данными в MySQL.

Если вы хотите получить бесплатные venue_ids на предлагаемую дату, вы должны написать что-то вроде:

  select ven.id, SUM('2009-12-06' between evtdt.event_from_datetime and evtdt.event_to_datetime) as num_intersects 
    from venues ven left join event_dates evtdt on (ven.id=evtdt.venue_id) 
    group by ven.id
    having num_intersects = 0;

, что дает:

+----+----------------+
| id | num_intersects |
+----+----------------+
|  2 |              0 |
+----+----------------+

это также дает правильный ответ (без изменений) в случае, если у вас есть место проведения без событий в таблице event_date.

0 голосов
/ 12 января 2010

По предположению, если вы удалите , а не из

or not ('2009-12-06 00:00:00' between evtdt.event_from_datetime 
                                  and evtdt.event_to_datetime)

тогда будет возвращена строка 1 из дат событий, но не строки других дат событий.

Я говорю «на догадку», потому что ваше положение where немного сложно понять. Может быть, вы имеете в виду

select ven.id , evtdt.event_from_datetime, evtdt.event_to_datetime 
from venues ven 
left join event_dates evtdt 
on (ven.id=evtdt.venue_id) 
where '2009-12-06 00:00:00' between evtdt.event_from_datetime 
                                  and evtdt.event_to_datetime;
...