为什么此查询仅返回1行?

时间:2013-01-27 11:36:10

标签: mysql sql sql-server database

请参阅表格结构,查询和结果。

MeetingRoom

   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     

ReservationTable

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 个答案:

答案 0 :(得分:4)

如果您使用LEFT OUTER JOIN并将WHERE clause设置条件设置为右侧表而不是IS NULL,则结果为INNER 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 

答案 1 :(得分:2)

你应该使用内部联接...... 的修改 您必须正在使用外连接,但请考虑空值与非空值的比较...

一种方法是使用OR子句

显式接受空日期值

答案 2 :(得分: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,你保留外连接但仍然过滤结果,而且你现在拥有最佳性能的查询版本。

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

答案 3 :(得分: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)