Finding free blocks of time in mysql and php?

前端 未结 4 1818
闹比i
闹比i 2020-12-01 11:43

I have a table in mysql like this:

+------------+------------+------------+------------+ 
|     date   |   user_id  | start_hour | end_hour   | 
+-----------         


        
相关标签:
4条回答
  • 2020-12-01 12:00

    Try this query

    SELECT
      a.id,
      a.start_hour,
      a.end_hour,
      TIMEDIFF(la.start_hour, a.end_hour) as `Free Time`
    FROM appointment as a
      LEFT JOIN(SELECT * FROM appointment LIMIT 1,18446744073709551615) AS la
        ON la.id = a.id + 1
      LEFT JOIN (SELECT * FROM appointment) AS ra ON a.id = ra.id
    

    This will show these results

    +---------------------------------------------+
    ¦ id ¦ start_hour BY ¦ end_hour   | Free Time |
    ¦----+---------------¦------------------------|
    ¦  1 ¦   08:00:00    ¦  08:15:00  | 05:45:00  |
    ¦  2 ¦   14:00:00    ¦  14:30:00  | 02:30:00  |
    ¦  3 ¦   17:00:00    ¦  17:45:00  | 03:15:00  |
    ¦  4 ¦   21:00:00    ¦  21:00:00  | (NULL)    |
    +--------------------+------------------------+ 
    

    Also you must have the 21:00:00 in the table or you wont be able to get the last time difference. i entered 21:00:00 as start and end date in the table.

    EDITED

    This is modified query

    SELECT
      a.id,
      a.end_hour AS `Free time Start`,
      IFNULL(la.start_hour,a.end_hour) AS `Free Time End`,
      IFNULL(TIMEDIFF(la.start_hour, a.end_hour),'00:00:00') AS `Total Free Time`
    FROM appointment AS a
      LEFT JOIN (SELECT * FROM appointment LIMIT 1,18446744073709551615) AS la
        ON la.id = (SELECT MIN(id) FROM appointment where id > a.id LIMIT 1)      
    

    And the result is

    +--------------------------------------------------------+
    ¦ id ¦ Free time Start ¦ Free Time End | Total Free Time |
    ¦----+-----------------¦---------------------------------|
    ¦  1 ¦   08:15:00      ¦ 14:00:00      |    05:45:00     |
    ¦  2 ¦   14:30:00      ¦ 17:00:00      |    02:30:00     |
    ¦  3 ¦   17:45:00      ¦ 21:00:00      |    03:15:00     |
    ¦  4 ¦   21:00:00      ¦ 21:00:00      |    00:00:00     |
    +----------------------+---------------------------------+  
    

    The points to learn from this query are

    1. Timediff function usage. timediff('end time','start time')
    2. Joining with upper number
    3. Avoid first record in join with a long offset and limit starting from 1 instead of zero
    4. IFNULL usage ifnull('if here comes null','select this then')
    0 讨论(0)
  • 2020-12-01 12:06

    Try this Query i hope its work for you.....

    SELECT
      a.id,
      a.end_hour    AS `Free time Start`,
      la.start_hour AS `Free Time End`,
      IFNULL(TIMEDIFF(la.start_hour, a.end_hour),'00:00:00') AS `Total Free Time`
    FROM appointment AS a
      LEFT JOIN (SELECT *
                 FROM appointment
                 LIMIT 1,18446744073709551615) AS la
        ON la.id = (SELECT
                      id
                    FROM appointment
                    WHERE id NOT IN(a.id)
                    ORDER BY (a.id > id)ASC
                    LIMIT 1);
    
    0 讨论(0)
  • 2020-12-01 12:10

    This will give you the end time blocks

    SELECT T_a.end_hour
    FROM (table AS T_a) LEFT JOIN (table AS T_b)
    ON (T_a.`date`=T_b.`date` AND T_b.start_hour<=T_a.end_hour AND T_b.end_hour>T_a.end_hour)
    WHERE T_b.user_id IS NULL
    

    This will give you the start time block

    SELECT T_a.start_hour
    FROM (table AS T_a) LEFT JOIN (table AS T_b)
    ON (T_a.`date`=T_b.`date` AND T_b.start_hour<T_a.start_hour AND T_b.end_hour>=T_a.start_hour)
    WHERE T_b.user_id IS NULL
    

    These queries will look for starts or ends that are uncrossed or butted up to other slots. so 10-11 11-12 will give 10 start, 12 end = free time is 08-10 and 12-21

    So free time is 08:00 (unless its a start time) upto first 'start' time, then matching pairs of END->START upto last END->21:00 (unless 21:00 IS the last end)

    N.B. You'll need to add the date in too.

    0 讨论(0)
  • 2020-12-01 12:23

    Perhaps this is over kill but this works on sql-server, not sure the effort to convert to mysql

    declare @AvailableTime table ( AvailableDate date,  StartTime time, EndTime time )
    
    insert into @AvailableTime values 
    ('15 dec 2010', '08:00:00', '21:00:00')
    
    declare @Booking table (BookingDate date, UserId int, StartTime Time, EndTime Time)
    
    insert into @Booking values 
    ('15 dec 2010', 20, '08:00:00', '08:15:00'),
    ('15 dec 2010', 20, '14:00:00', '14:30:00'),
    ('15 dec 2010', 20, '17:00:00', '17:45:00')
    
    select 
        *
    from
    (
        -- first SELECT get start boundry
        select t.StartTime s, b.StartTime e
        from @AvailableTime t, @Booking b
        where 
            t.AvailableDate = b.BookingDate and (t.StartTime <= b.EndTime and b.StartTime <= t.EndTime) and t.StartTime <> b.StartTime
        and
            not exists (select 1 from @Booking b2 where b2.BookingDate = b.BookingDate and b2.StartTime < b.StartTime)
    
        union
    
        -- second SELECT get spikes ie middle
        select b1.EndTime s, b2.StartTime e
        from @AvailableTime t, @Booking b1, @Booking b2
        where 
            t.AvailableDate = b1.BookingDate and (t.StartTime <= b1.EndTime and b1.StartTime <= t.EndTime) 
        and 
            t.AvailableDate = b2.BookingDate and (t.StartTime <= b2.EndTime and b2.StartTime <= t.EndTime) 
        and 
            b1.EndTime < b2.StartTime
        and
            not exists (select 1 from @Booking b3 where b3.BookingDate = t.AvailableDate and b3.StartTime > b1.EndTime and b3.EndTime < b2.StartTime)
    
        union
    
        -- third SELECT get end boundry
        select b.EndTime s, t.EndTime e
        from @AvailableTime t, @Booking b
        where 
            t.AvailableDate = b.BookingDate and (t.StartTime <= b.EndTime and b.StartTime <= t.EndTime) and t.EndTime <> b.EndTime
        and 
            not exists (select 1 from @Booking b2 where b2.BookingDate = b.BookingDate and b2.StartTime > b.StartTime)
    ) t1
    
    0 讨论(0)
提交回复
热议问题