【问题标题】:Find available time slots with SQL使用 SQL 查找可用时隙
【发布时间】:2013-11-27 16:15:00
【问题描述】:

我在这里找到了一个answer 关于在数据库中查找可用时隙的常见问题。该查询就像一个魅力,但如果我添加一个在已经添加的事件之前开始的新事件,它就会开始失败。在这种情况下,输出的顺序是错误的。答案中已经有一个sqlFiddle 示例,我只是在架构中添加了一个新行:

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

如您所见,活动日期早于上次插入的活动日期(它们不再按 timeBooked 的顺序排列)。也许我试图将太多逻辑放入查询中,如果是这样,那么我怎么能用 PHP 来处理这件事呢?

编辑

可能我应该先展平时间戳,然后对结果执行查询。我发现something 可以使时间戳变平,但我需要帮助来合并这两个查询并为生产优化一些东西

【问题讨论】:

  • 对不起,这是一个错字(jsFiddle -> sqlFiddle):D 无论如何,只要看看我编辑过的小提琴的输出,你就会发现前两行显然是错误的,因为间隔 2013-05 -10 00:00:00 - 2013-05-13 13:22:00 不是全部免费,里面有我的问题的事件

标签: php mysql sql


【解决方案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

显然,您可以在没有视图的情况下重写它——我只是发现很难阅读所有那些“+ INTERVAL”位。

【讨论】:

  • 感谢您的回复,感谢您的帮助。但是,您的查询不适用于重叠的时间跨度。你能帮我修一下吗?
  • 还有一个小问题:如果事件有 user_id 属性并且我需要过滤用户的空闲槽,我应该只将 WHERE 条件放在视图中吗?
  • 我猜你可以 - 但这似乎有点乏味。但是,如果我们要坚持使用视图(并记住它所做的只是将持续时间添加到 starttime),那么我会修改它以包含所有 user_id 信息,然后修改查询以使用它。见小提琴sqlfiddle.com/#!2/6341ff/10
  • 我在编辑表格时并不真正需要视图,现在我有了 start_date 和 end_date 而不是持续时间列。也许这个讨论时间太长了,我想在优化这个查询方面获得更多帮助,但也许这不是正确的地方,我们应该在聊天中讨论(如果你有时间的话)。
  • 我认为更好的办法是提出一个关于查询优化的新问题(不是我的强项),然后再参考这个帖子。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多