2

请查看表结构、查询和结果。

会议室

   ID | Area | RoomNo    Capacity   distances 
   --- ----- --------- ---------- ----------
   1   1     R1         10        10        
   2   1     R3         24        4         
   3   8     R4         24        4         
   4   1     R5         10        10     

预订表

ReservationID RoomID      DateTimeStart           DateTimeEnd             
------------- ----------- ----------------------- ----------------------- 
1             1           2013-10-10 17:00:00.000 2013-10-10 19:00:00.000 

询问

 Declare @Start Datetime
 Declare @End Datetime

 set @Start='2013-10-10 13:00:00.000'
 set @End='2013-10-10 14:00:00.000'

 select 
     MeetingRoom.ID 
 from 
    MeetingRoom 
    left Join ResReservationTable Res on Res.RoomID = MeetingRoom.ID
 Where 
   Res.DateTimeStart != @Start and Res.DateTimeEnd != @End
   and (Res.DateTimeStart Not Between @Start and @End) 
   and (Res.DateTimeEnd Not Between @Start and @End)

此查询仅返回一条记录,因为它应该返回 4 条记录

4

4 回答 4

4

如果您在右侧表格LEFT OUTER JOIN 中使用 and设置条件而不是在结果中使用.WHERE clauseIS NULLINNER JOIN

我想这就是你想要的。

Declare @Start Datetime
Declare @End Datetime

set @Start='2013-10-10 13:00:00.000'
set @End='2013-10-10 14:00:00.000'

select 
     MeetingRoom.ID 
from 
    MeetingRoom 
    left Join ResReservationTable Res on Res.RoomID = MeetingRoom.ID
Where
  (
   Res.DateTimeStart != @Start and Res.DateTimeEnd != @End
   and (Res.DateTimeStart Not Between @Start and @End) 
   and (Res.DateTimeEnd Not Between @Start and @End)
  )
  OR Res.ReservationID IS NULL

我认为你必须重新表述你的WHERE情况。如果你想要完全空闲的空间(即间隔不相交),你可以使用这个:

WHERE
   Res.DateTimeStart > @End
   OR Res.DateTimeEnd < @Start
   OR Res.ReservationID IS NULL 
于 2013-01-27T11:44:13.427 回答
2

最好的方法是将 WHERE 子句中的内容移到 ON 子句中:

select 
    MeetingRoom.ID 
from MeetingRoom 
left Join ResReservationTable Res on Res.RoomID = MeetingRoom.ID
and Res.DateTimeStart != @Start and Res.DateTimeEnd != @End
and Res.DateTimeStart Not Between @Start and @End
and Res.DateTimeEnd Not Between @Start and @End

嘿 presto,您保留了外部联接,但仍过滤结果,而且您​​现在拥有性能最佳的查询版本。

这是一个非常常见且不正确的假设,即连接条件可能只有“键相关”表达式,但实际上您可以有任何条件,甚至是连接表中未涉及的列上的条件。

于 2013-01-27T11:53:27.087 回答
2

你能试试这个吗?它使用“Outer”并检查为没有预订的房间返回的 NULL 值并返回这些行。

Declare @Start Datetime
 Declare @End Datetime

 set @Start='2013-10-10 13:00:00.000'
 set @End='2013-10-10 14:00:00.000'

 select 
     MeetingRoom.ID 
 from 
    MeetingRoom 
    left Outer Join ResReservationTable Res on Res.RoomID = MeetingRoom.ID
 Where 
   (Res.DateTimeStart is NULL OR Res.DateTimeEnd is NULL)
   and Res.DateTimeStart != @Start and Res.DateTimeEnd != @End
   and (Res.DateTimeStart Not Between @Start and @End) 
   and (Res.DateTimeEnd Not Between @Start and @End)
于 2013-01-27T11:59:52.343 回答
2

您应该使用内部联接... 编辑 您必须照常使用外部联接,但要考虑空值与非空值的比较...

一种方法是使用 OR 子句显式接受空日期值

于 2013-01-27T11:39:57.437 回答