查询以避免不同时隙的冲突

时间:2012-05-02 16:32:23

标签: mysql performance

我在几个地方寻找过这个但不一定找到正确的答案。

我正在尝试查询给定时间范围内的可用提供商。我有一个列,其中包含所有带有date_start和date_end的旧预订。基本上,如果我想预订,我需要确保我的提供商可用。到目前为止,查询的工作原理如下:

  SELECT a.provider a
      FROM l_provider_zip a 
      (several inner Joins and conditions)
      WHERE a.zip = :zip 

 AND a.provider_id  
 NOT IN (
     SELECT da.provider_id
     FROM booking da
     WHERE da.provider_id IS NOT NULL
       AND (
              ( :start BETWEEN da.date_start AND da.date_end) 
           OR ( :end  BETWEEN da.date_start AND da.date_end) 
           OR ( da.date_start BETWEEN :start AND :end )
           )
)

我担心的是,为了找出可用于新预订的提供商,我需要确保新预订不会与其他预订冲突。在这里,我有3个条件陈述来解决它。

  1. :开始(新预订)BETWEEN da.date_start AND da.date_end
  2. :结束(新预订)BETWEEN da.date_start AND da.date_end
  3. da.date_start BETWEEN:开始AND:结束(另一个预订不在新单位的开头或结尾)
  4. 这似乎效率很低但我找不到更好的方法。当然,我可以通过索引使其更有效,但是有更好的方法来执行此操作。这对我的项目来说是一个中心问题,我认为这可能是许多人面临的问题,并将继续面对。再次感谢!

2 个答案:

答案 0 :(得分:2)

如果我理解了您的问题,那么您正在寻找可用于此预订的提供商,即那些没有预订与此预订相冲突的提供商。因此,要查找与此预订相冲突的所有预订,您需要查找预订

- where the booking start date is on or before the new booking end date, and
- where the booking end date is on or after the new booking start date

因此,您的子查询将转换为

 SELECT da.provider_id
 FROM booking da
 WHERE da.provider_id IS NOT NULL
   AND da.date_start <= :end 
   AND da.date_end   >= :start

答案 1 :(得分:1)

我会将提供商加入到指定日期范围内的预订中,然后将这些提供商排除在外:

/* Select all providers */
SELECT *
FROM l_provider_zip p
/* Providers with bookings that start in the middle of our date range are busy */
LEFT JOIN booking b1
  ON b1.provider_id = p.provider_id
  AND b1.date_start BETWEEN :start AND :end
/* Providers with bookings that end in the middle of our date range are busy */
LEFT JOIN booking b2
  ON b2.provider_id = p.provider_id
  AND b2.date_end BETWEEN :start AND :end
/* Exclude those providers with bookings in our date range */
WHERE b1.provider_id IS NULL
  AND b2.provider_id IS NULL

不需要子查询!如果您需要索引方面的帮助,请告诉我,以使此查询运行良好。