PHP / MySQL - 检查双人会议室预订

PHP / MySQL  - 检查双人会议室预订

问题描述:

I want to find rows for anytime during the new period I'm requesting.

Here is my table data which has existing rows:

https://www.dropbox.com/s/1s4y8tl6s09emim/Screenshot%202014-04-04%2009.52.24.png

Here is the new period I'm requesting:

Date: 2014-04-03 
Start Time: 12:30:00
End Time: 13:30:00

What is the correct SQL to find any existing rows for anytime during the new period I'm requesting?

I have this so far but not sure about the start_time and end_time fields.

$sql = 'SELECT * FROM int_low_events WHERE start_date = "2014-04-03"';

我想在我申请的新时期内随时查找行。 p>

这是我的表数据,其中包含现有行: p>

  https://www.dropbox.com/s/1s4y8tl6s09emim/Screenshot%202014-04-04%2009.52  .24.png 
  code>  pre> 
 
 

这是我要求的新期间: p>

 日期:2014-04  -03 
开始时间:12:30:00 
结束时间:13:30:00 
  code>  pre> 
 
 

正确的 SQL code>是什么 在我要求的新时间段内随时查找任何现有行? p>

到目前为止我有这个但是不确定 start_time code>和 end_time fields。 p>

  $ sql ='SELECT * FROM int_low_events WHERE start_date =“2014-04-03”'; 
  code>  pre> 
  div>

SELECT *, 
       ADDTIME(start_date, start_time) AS start,
       ADDTIME(end_date, end_time) AS end,
       '2014-04-03 14:00:00' AS proposed_start,
       '2014-04-03 16:05:00' AS proposed_end
  FROM int_low_events
HAVING (start BETWEEN proposed_start AND proposed_end OR end BETWEEN proposed_start AND proposed_end)
    OR (proposed_start BETWEEN start AND end OR proposed_end BETWEEN start AND end)

This is exactly the same as my previous (working) answer, but it is (in my opinion) a lot easier to understand. Also you now don't have to fill in the proposed start- and end-dates everywhere, but instead only once (... AS proposed_start and ... AS proposed_end).

This does work according to this SQLFiddle with your database design.


It needs to be so complicated, as it needs to fetch any event, that's running at the time of the new proposed event.

id | start_date | start_time | end_date   | end_time
---+------------+------------+------------+-----------
62 | 2014-04-03 | 12:00:00   | 2014-04-05 | 13:00:00
63 | 2014-04-03 | NULL       | 2014-04-04 | NULL
64 | 2014-04-03 | 16:00:00   | 2014-04-03 | 17:00:00
65 | 2014-04-03 | 16:30:00   | 2014-04-03 | 17:30:00
66 | 2014-04-03 | 21:30:00   | 2014-04-03 | 22:30:00

This is the part of your database that matters. Assume we have a new event, that has the following dates: 2014-04-03 16:00 - 2014-04-03 18:00. With my previous query, it only selected the IDs 64 and 65 (as both of these have either the start_datetime OR end_datetime within our new event).

However ID 62 does also span over this timeframe, but starts earlier AND ends later. With the new query, this will also be selected (if this makes any sense to you).

I suppose you have I field date in your table:

 $sql = 'SELECT * FROM int_low_events WHERE date between '2014-04-03 12:30:00' and '2014-04-03 13:30:00'";

Here's an idea to check if two events are overlapping : you could use BETWEEN like this :

SELECT a.event_id, b.event_id 
FROM int_low_events AS a, int_low_events AS b
WHERE b.site_id = a.site_id AND
b.start_date = a.start_date AND
b.start_time BETWEEN a.start_time and a.end_time

This will work for events during less than one day, as the ones in your database screenshot.

You may need to adapt it for events during more than one day.

So despite this being billed as a PHP question, it's actually a database question?? ;-)

Hopefully your date-time combination are already encoded in the table as a date-time field, and not as two separate date and time fields. If this is not the case, then I strongly suggest that you build a view which combines these two fields into one. Drastically simplifies your SQL, and your maintenance costs (for anyone trying to modify in the future).

If you don't do this, then you will have serious problems when searching on events which span several days, as is evident in other answers on this page.

Also, you need to change your incoming request to a date-time combination. You can do this in your PHP code before binding to the SQL variable.

The SQL then looks like this...

select *
from   int_low_events a
where  :proposed_start_datetime not between a.start_datetime and a.end_datetime
  and  :proposed_end_datetime not between a.start_datetime and a.end_datetime

-- edit -- Depending on which database you have underlying all this, there are different ways to combine the date and time fields. Use ADDTIME() if you're using MySQL. Other databases will have their own ways of doing the same thing, thus allowing you to build the solution into your SQL rather than having to modify the database logic.