2013-11-27 4 views
0

Я нашел answer здесь, на странице about о общей проблеме поиска доступных временных интервалов в базе данных. Запрос работает как прелесть, но он начинает терпеть неудачу, если я добавляю новое событие, которое начинается до добавления добавленных alredy. В этом случае порядок вывода неверен. Существует настройки уже sqlFiddle примера в ответе, я просто добавил в схеме новой строки:Найти доступные временные интервалы с SQL

insert into bookingEvents values (null, '2013-05-12 05:11:00', 15); 

Как вы можете видеть, что дата этого события до даты последнего ранее вставленного мероприятия (они не больше в порядке timeBooked). Может быть, я пытаюсь включить слишком много логики в запрос, если это так, то как я могу обработать эту вещь с помощью PHP тоже?

EDIT

Вероятно, я должен сначала сглаживать временные метки, а затем выполнить запрос на результат. Я нашел something выравниваться метки времени, но мне нужна помощь, чтобы объединить два запроса и получить что-то оптимизированное для производства

+0

Извините, что это была опечатка (jsFiddle -> sqlFiddle): D В любом случае, просто посмотрите на выход моей отредактированной скрипки, и вы увидите, что первые две строки явно неправильны, потому что интервал 2013-05-10 00:00 : 00 - 2013-05-13 13:22:00 не все бесплатно, есть событие моего вопроса внутри – Stefano

ответ

1

Чтобы сохранить свое здравомыслие, я создал представление следующим образом ...

CREATE VIEW v_bookingevents AS 
    SELECT id 
      , timebooked startdate 
      , timebooked + INTERVAL duration MINUTE enddate 
     FROM bookingevents 
     ORDER 
     BY startdate; 

Тогда ...

SELECT a.enddate 'Available From' 
     , MIN(b.startdate) 'To' 
    FROM 
    ( 

     SELECT DISTINCT 
      COALESCE(LEAST(x.startdate,y.startdate),x.startdate) startdate 
      , COALESCE(GREATEST(x.enddate,y.enddate),x.enddate) enddate 
     FROM v_bookingevents x 
     LEFT 
     JOIN v_bookingevents y 
      ON y.id <> x.id 
     AND y.startdate < x.enddate 
    AND y.enddate > x.startdate 
    UNION 
    SELECT '2013-05-12 00:00:00' 
       , '2013-05-12 00:00:01' 

    ) a 
    JOIN 
    (  
    SELECT DISTINCT 
     COALESCE(LEAST(x.startdate,y.startdate),x.startdate) startdate 
     , COALESCE(GREATEST(x.enddate,y.enddate),x.enddate) enddate 
    FROM v_bookingevents x 
    LEFT 
    JOIN v_bookingevents y 
     ON y.id <> x.id 
    AND y.startdate < x.enddate 
    AND y.enddate > x.startdate 

     UNION 
     SELECT '2013-05-15 00:00:00' 
      ,'2013-05-15 00:00:01' 
    ) b 
    ON b.startdate > a.enddate 
GROUP 
    BY a.enddate 
HAVING a.enddate < MIN(b.startdate); 

http://sqlfiddle.com/#!2/e67b47/1

Очевидно, что вы могли бы переписать это без зрения - я только что нашел его трудно читать аль l эти бит «+ INTERVAL».

+0

спасибо за ответ, я ценю вашу помощь. Однако ваш запрос не работает с временными интервалами, которые перекрываются. Можете ли вы помочь мне исправить это? – Stefano

+0

еще один маленький вопрос: если события имеют свойство user_id, и мне нужно отфильтровать свободные слоты пользователя, должен ли я поставить условие WHERE только в представлении? – Stefano

+0

Я думаю, вы могли бы - но это кажется немного утомительным. Однако, если мы будем придерживаться представления (и помните, что все это означает добавление продолжительности к началу), я бы вносил поправки, чтобы включить всю информацию user_id, а затем изменить запрос, чтобы использовать это. См. Скрипку http://sqlfiddle.com/#!2/6341ff/10 – Strawberry

Смежные вопросы