Mysql 查询以避免不同时段的冲突

Mysql 查询以避免不同时段的冲突,mysql,performance,Mysql,Performance,我在好几个地方寻找过这个问题,但不一定找到了正确的答案 我正在尝试查询给定时间范围内的可用提供者。我有一个专栏,里面有所有的老预订,有开始日期和结束日期。基本上,如果我想预订,我需要确保我的供应商是可用的。到目前为止,查询工作如下: SELECT a.provider a FROM l_provider_zip a (several inner Joins and conditions) WHERE a.zip = :zip AND a.provi

我在好几个地方寻找过这个问题,但不一定找到了正确的答案

我正在尝试查询给定时间范围内的可用提供者。我有一个专栏,里面有所有的老预订,有开始日期和结束日期。基本上,如果我想预订,我需要确保我的供应商是可用的。到目前为止,查询工作如下:

  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个条件语句来解释它

:在da.date\开始和da.date\结束之间开始新预订 :在da.date\u开始和da.date\u结束之间结束新预订 da.date\u start BETWEEN:start AND:end另一个预订不在新预订的开始或结束处
这似乎效率很低,但我找不到更好的方法。当然,我可以通过索引来提高效率,但是有没有更好的方法来执行这个操作呢。这是我的项目的一个核心问题,我认为这可能是许多人已经面临并将继续面临的一个问题。再次感谢

我会在指定的日期范围内加入提供商进行预订,然后排除这些提供商,因为它们被占用了:

/* 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

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

我会将提供程序加入到指定日期范围内的预订中,然后排除这些提供程序,因为它们已被占用:

/* 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

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

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

- 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

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

- 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

第一个和第三个条件是否包含第二个条件,即第二个条件是不必要的?我看不出2是真的,但1和3不是。第一个和第三个条件不是包含第二个条件吗,即第二个条件是不必要的?我看不出2是真的,但1和3不是。我喜欢这样,但我认为我应该将not exists转换为not in以减少子查询返回的行数:not exists SELECT*FROM BOOTING da where da.provider\U id=a.provider\U id和da.date\U start=:start@TheVedge我想,根据其他联接,您可能可以在上面的查询上保留联接,并使用IS NULL,这可能会提高性能。如果看不到OP的完整模式,很难知道,解释输出etcThanks很多,这正是我需要的。我喜欢这样,但我想我应该将notexists转换为notin,以减少子查询返回的行数:notexists SELECT*FROM booking da WHERE da.provider\u id=a.provider\u id和da.date\u start=:start@TheVedge我想,根据其他联接,您可能可以在上面的查询上保留联接,并使用IS NULL,这可能会提高性能。如果看不到OP的完整模式,就很难知道,解释输出等等,这正是我所需要的。