开发者

Need to query for users who have time conflicts, and return those time conflicts

This is a question that builds off of one of my previous questions. The tables are the same:

Users
------------------------------------
UserID | Name      | Assignable
------------------------------------
  5    | John开发者_C百科 Doe  |      1

TimeSlots
-------------------------------------------------------
TimeSlotID | StartTime           | EndTime
-------------------------------------------------------
     3     | 2011-06-30 15:00:00 | 2011-06-30 16:00:00

Appointments
------------------------------------
TimeSlotID | UserID
------------------------------------
     3     |    5   

The accepted answer helped me find users who were available for a certain time span. I need some way to input a start date/time and an end date/time and return any TimeSlots that conflict with those datetimes (they are in between the start/end dates, at the start/end times). But I need it to be organized by user, so:

If I input 2011-07-05 for the start date and 2011-07-07 for the end date, then I input 07:00 for the start time and 19:00 for the end time. And I have two users (User 1 and User 2), one who has no Appointments and one who has an Appointment on 2011-07-06 11:00. I would need the results to be something like:

User 1: NULL

User 2: (Array of TimeSlots that conflict)

EDIT: Don't know if I was clear enough with the start/end dates and times. It would only look for conflicts between the start and end times on each date (inclusive) between the start and end date.


A slight modification on the previous answer - to catch those timeslots that start in your interval and end after it or start before your interval and end during it (technically still a conflict in your definition):

SELECT
   UserID
   GROUP_CONCAT(CONCAT(StartTime, ' - ', EndTime)) slots
FROM
   Users
   LEFT JOIN Appointments a USING (UserID)
   LEFT JOIN TimeSlots ts ON (
      a.TimeSlotID = ts.TimeSlotID
      AND ( ts.EndTime > @start AND ts.StartTime > @end
            OR ts.EndTime between @start and @end
            OR ts.StartTime between @start and @end )
   )
GROUP BY
   UserID
ORDER BY
   UserID

If you don't want to use concatenation, then just return each timeslot and convert the results into arrays in your php code. In this case, your SQL will be

SELECT
   UserID,
   CONCAT(StartTime, ' - ', EndTime) slot
FROM
   Users
   LEFT JOIN Appointments a USING (UserID)
   LEFT JOIN TimeSlots ts ON (
      a.TimeSlotID = ts.TimeSlotID
      AND ( ts.EndTime > @start AND ts.StartTime > @end
            OR ts.EndTime between @start and @end
            OR ts.StartTime between @start and @end )
   )
ORDER BY
   UserID, StartTime


MySQL cannot return arrays, but you can come close with the following:

SELECT
   UserID,
   GROUP_CONCAT(CONCAT(StartTime, ' - ', EndTime)) slots
FROM
   Users
   LEFT JOIN Appointments a USING (UserID)
   LEFT JOIN TimeSlots ts ON (
      a.TimeSlotID = ts.TimeSlotID
      AND ts.EndTime > @start
      AND ts.StartTime > @end
   )
GROUP BY
   UserID

This will give you a comma-separated list (or NULL) of time slots per a user.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜