2013-05-09 2 views
0

я иметь эту структуру таблицы для заказаMySQL показывает временные интервалы и имеющиеся временные интервалы заняты из таблицы

|ID|timeBooked   | duration | 
|2 |2013-05-09 11:10:00| 30  | 
|1 |2013-05-09 14:40:00| 15  | 
|AI| timespan   | int(4) | 

продолжительность представляет продолжительность в минутах.

так, что я хочу, чтобы вернуть рекорд, как это, когда я

запроса доступные временные интервалы в 2013-05-09 между 00:00:00 и 23:00:00

|free_from|Free_until| Free | 
|00:00:00 |11:10:00 | 1 
|11:10:00 |11:40:00 | 0 
|11:40:00 |14:40:00 | 1 
|14:40:00 |14:55:00 | 0 
|14:55:00 |23:00:00 | 1 

возможно ли это только mysql?

ответ

5

ОК, чистый MySQL - до тех пор, как один любит эти трюки. Мне нужна переменная, которая инициализируется «Начало» периодов для показа, что-то вроде now() обычно.

Прежде всего данные испытаний:

create table bookingEvents 
    (id int not null primary key auto_increment, 
    timeBooked datetime, 
    duration int 
    ); 


insert into bookingEvents values (null, '2013-05-13 13:22:00', 15); 
insert into bookingEvents values (null, '2013-05-13 15:10:00', 45); 
insert into bookingEvents values (null, '2013-05-13 19:55:00', 30); 
insert into bookingEvents values (null, '2013-05-14 03:22:00', 15); 
insert into bookingEvents values (null, '2013-05-14 08:19:00', 15); 

Затем инициализацией "слайдер":

set @timeSlider='2013-05-10 00:00:00'; 

Затем выберите:

select if (d.name = 'Free', @timeSlider, b.timeBooked) as free_from, 
     if (d.name = 'Free', b.timeBooked, @timeSlider := b.timeBooked + interval b.duration minute) as free_until, 
     d.name as Free 
from (select 1 as place, 'Free' as name union select 2 as place, 'Booked' as name) d 
inner join bookingEvents b 
having free_from < free_until 
order by b.timeBooked, d.place; 

Результат:

+---------------------+---------------------+--------+ 
| free_from   | free_until   | Free | 
+---------------------+---------------------+--------+ 
| 2013-05-10 00:00:00 | 2013-05-13 13:22:00 | Free | 
| 2013-05-13 13:22:00 | 2013-05-13 13:37:00 | Booked | 
| 2013-05-13 13:37:00 | 2013-05-13 15:10:00 | Free | 
| 2013-05-13 15:10:00 | 2013-05-13 15:55:00 | Booked | 
| 2013-05-13 15:55:00 | 2013-05-13 19:55:00 | Free | 
| 2013-05-13 19:55:00 | 2013-05-13 20:25:00 | Booked | 
| 2013-05-13 20:25:00 | 2013-05-14 03:22:00 | Free | 
| 2013-05-14 03:22:00 | 2013-05-14 03:37:00 | Booked | 
| 2013-05-14 03:37:00 | 2013-05-14 08:19:00 | Free | 
| 2013-05-14 08:19:00 | 2013-05-14 08:34:00 | Booked | 
+---------------------+---------------------+--------+ 

Если у Вас есть данный End-Timestamp, то вы должны предварительно установить, что в качестве @timeMaximum

set @timeSlider='2013-05-10 00:00:00'; 
set @timeMaximum='2013-05-14 08:35:00'; 


select if (d.name = 'Free', @timeSlider, b.timeBooked) as free_from, 
     if (d.name = 'Free', b.timeBooked, @timeSlider := b.timeBooked + interval b.duration minute) as free_until, 
     d.name as Free 
from (select 1 as place, 'Free' as name union select 2 as place, 'Booked' as name) as d 
inner join bookingEvents b 
having free_from < free_until 
union select @timeSlider as free_from, @timeMaximum as free_until, 'Free' as Free 
from (select 1) as d 
where @timeSlider < @timeMaximum 

order by free_from, free_until 
; 
+0

приятно :) я люблю его и время выполнения 0,003 поэтому не так уж плохо :) .. спасибо – Zalaboza

1

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

SELECT id, 
    DATE_FORMAT(timeBooked, '%H:%i:%s') AS initial_time, 
    DATE_FORMAT(DATE_ADD(timeBooked, INTERVAL duration MINUTE), '%H:%i:%s') AS final_time, 
    duration 
FROM your_table t1 
WHERE DATE(timeBooked) = '2013-05-09' 
ORDER BY t1.timeBooked ASC; 

Я надеюсь, что это пригодится!

1

EDIT: Обеспокоенный моим другим ответом. Пока вы просто проходите через заказываемые данные, производительность должна быть хорошей.

Старый:

Я думаю, что в SQL одиночку решение будет получить очень медленно, как только разумное количество строк в таблице.

SQL-таблица сама по себе не исключает перекрытия.

Я хотел бы использовать таблицу так:

CREATE TABLE bookingEvents (id int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT, 
    event ENUM('start', 'end') NOT NULL, 
    bookingId INT(11) NOT NULL, 
    eventTime DATETIME NOT NULL, 
    index (eventTime) 
); 

где bookingId ссылается на дополнительную таблицу с информаций о бронировании.

Тогда вы можете перечислить так:

SELECT event, eventTime 
FROM bookingEvents 
WHERE (date or something) 
ORDER BY eventTime; 

вы получаете (до тех пор, как заказы не пересекаются) чередующиеся bookingStart и bookingEnd- раз, что заполняют как

time1 time2 booked 
time2 time3 free 
time3 time4 booked 
time4 time5 free 

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

Вставка заказа так просто, как

INSERT INTO bookingEvents (event, bookingId, eventTime) 
VALUES ('start', $bookingId, $timeBooked       ), 
     ('end' , $bookingId, $timeBooked + interval $length minute) 
; 
Смежные вопросы