【问题标题】:Why This Query is returning only 1 Row?为什么此查询仅返回 1 行?
【发布时间】:2013-01-27 11:36:10
【问题描述】:

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

会议室

   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 条记录

【问题讨论】:

  • 什么是 Res?里面的数据是什么?那么为什么不向我们展示其中的数据呢?它包含多少行和 RoomID 值?
  • @PreetSangha Res 是表名,包含会议室的预订详情
  • 您认为这将返回四条记录。从您的加入中可以清楚地看出,只有一行与您的条件相匹配。如果 ReservationTable RoomID 在 MeetingRoom 中使用了更多时间,那么您可以查看更多结果....
  • 因为我使用的是左连接,所以它应该带来 3 条不在 Reservation 表中的记录和 1 条记录,因为这条记录的条件为真

标签: mysql sql sql-server database


【解决方案1】:

如果您使用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 

【讨论】:

  • 在这个查询中,如果我给出像 set @Start='2013-10-10 17:00:00.000' set @End='2013-10-10 19:00:00.000' 这样的值它返回 4 行,因为它应该返回 3
  • :) 谢谢...完全是我需要的
  • 我将您的答案标记为正确,因为它工作正常。但现在我遇到了问题。如果 ResReservationTable 问题中的一个房间有多个记录,则此查询将返回该房间也在给定日期时间保留,因为该房间的条件为真。
【解决方案2】:

您应该使用内连接... 编辑 您必须像现在一样使用外连接,但要考虑空值与非空值的比较...

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

【讨论】:

  • 即使使用内连接也返回相同的结果。
【解决方案3】:

你可以试试这个吗?它使用“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)

【讨论】:

  • 它甚至没有带来 1 条记录,应该带来 4 条记录
【解决方案4】:

最好的方法是将 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

嘿,你好,你保留了外连接,但仍然过滤了结果,而且你现在拥有了性能最好的查询版本。

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

【讨论】:

  • 在这个查询中,如果我给出像 set @Start='2013-10-10 17:00:00.000' set @End='2013-10-10 19:00:00.000' 这样的值它返回 4 行,因为它应该返回 3
猜你喜欢
  • 2016-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-02
  • 2021-04-29
  • 2014-01-26
  • 2011-11-24
相关资源
最近更新 更多