WHERE 子句,其中一些参数可以为 null
WHERE clause where some parameters can be null
我的任务是提取开始时间和结束时间内的记录数,同时 可能 被@aircraftId、@instructorId 和@reservationId 过滤掉(所以它在计数中忽略自身)。所有三个参数都可以为空,因此它们可能会或可能不会被传递,因此查询必须根据它们是否存在进行过滤。我可以使用动态 Sql 来做到这一点,但我更愿意避免它,主要是因为对于以后必须处理它的任何人来说调试都是一件痛苦的事情。
这是否可能(我猜是)在单个查询中?或者,这是我必须抓住设置并将其与其他参数一起削减(如果存在)的情况之一吗?
SELECT COUNT(*)
FROM AVMAN.Reservation
WHERE ( @aircraftid IS NULL
OR ( @aircraftid IS NOT NULL
AND AircraftId = @aircraftid
)
)
OR ( @InstructorId IS NULL
OR ( @InstructorId IS NOT NULL
AND InstructorUserId = @InstructorId
)
)
AND ( ( -- start during the range
StartTime >= @StartTime
AND StartTime < @EndTime
)
OR ( -- end during the range
EndTime > @StartTime
AND EndTime <= @EndTime
)
OR ( -- start before the range and end after it
StartTime < @StartTime
AND EndTime > @EndTime
)
)
AND ( @ReservationId IS NULL
OR ( ReservationId IS NOT NULL
AND ReservationId = @ReservationId
)
)
我不确定,但尝试像这样在 WHERE 子句中使用 CASE
SELECT COUNT(*)
FROM AVMAN.Reservation
WHERE CASE
WHEN @aircraftid IS NULL THEN 1
WHEN @aircraftid IS NOT NULL AND AircraftId = @aircraftid THEN 1
END = 1
AND
CASE
WHEN @InstructorId IS NULL THEN 1
WHEN @InstructorId IS NOT NULL AND InstructorUserId = @InstructorId THEN 1
END = 1
AND ( ( -- start during the range
StartTime >= @StartTime
AND StartTime < @EndTime
)
OR ( -- end during the range
EndTime > @StartTime
AND EndTime <= @EndTime
)
OR ( -- start before the range and end after it
StartTime < @StartTime
AND EndTime > @EndTime
)
)
AND
CASE
WHEN @ReservationId IS NULL THEN 1
WHEN ReservationId IS NOT NULL AND ReservationId = @ReservationId THEN 1
END = 1
首先,在您原来的 SQL 中,您使用的是 OR 而不是 AND,这会影响您的结果。
要整理 aircraftId、instructorId 和 reservationId 上的过滤器,您可以执行以下操作:
SELECT COUNT(*)
FROM AVMAN.Reservation
WHERE
ISNULL( @AircraftId, AircraftId ) = AircraftId
AND
ISNULL( @InstructorId, InstructorId ) = InstructorId
AND
ISNULL( @ReservationId, ReservationId ) = ReservationId
AND
( ( -- start during the range
StartTime >= @StartTime
AND StartTime < @EndTime
)
OR ( -- end during the range
EndTime > @StartTime
AND EndTime <= @EndTime
)
OR ( -- start before the range and end after it
StartTime < @StartTime
AND EndTime > @EndTime
)
)
ISNULL 基本上是在 AircraftId 不为空时将 AircraftId 与 @AircraftId 进行比较,而在 @AircraftId 为空时则与 AircraftId(显然始终相同)进行比较。
我的任务是提取开始时间和结束时间内的记录数,同时 可能 被@aircraftId、@instructorId 和@reservationId 过滤掉(所以它在计数中忽略自身)。所有三个参数都可以为空,因此它们可能会或可能不会被传递,因此查询必须根据它们是否存在进行过滤。我可以使用动态 Sql 来做到这一点,但我更愿意避免它,主要是因为对于以后必须处理它的任何人来说调试都是一件痛苦的事情。
这是否可能(我猜是)在单个查询中?或者,这是我必须抓住设置并将其与其他参数一起削减(如果存在)的情况之一吗?
SELECT COUNT(*)
FROM AVMAN.Reservation
WHERE ( @aircraftid IS NULL
OR ( @aircraftid IS NOT NULL
AND AircraftId = @aircraftid
)
)
OR ( @InstructorId IS NULL
OR ( @InstructorId IS NOT NULL
AND InstructorUserId = @InstructorId
)
)
AND ( ( -- start during the range
StartTime >= @StartTime
AND StartTime < @EndTime
)
OR ( -- end during the range
EndTime > @StartTime
AND EndTime <= @EndTime
)
OR ( -- start before the range and end after it
StartTime < @StartTime
AND EndTime > @EndTime
)
)
AND ( @ReservationId IS NULL
OR ( ReservationId IS NOT NULL
AND ReservationId = @ReservationId
)
)
我不确定,但尝试像这样在 WHERE 子句中使用 CASE
SELECT COUNT(*)
FROM AVMAN.Reservation
WHERE CASE
WHEN @aircraftid IS NULL THEN 1
WHEN @aircraftid IS NOT NULL AND AircraftId = @aircraftid THEN 1
END = 1
AND
CASE
WHEN @InstructorId IS NULL THEN 1
WHEN @InstructorId IS NOT NULL AND InstructorUserId = @InstructorId THEN 1
END = 1
AND ( ( -- start during the range
StartTime >= @StartTime
AND StartTime < @EndTime
)
OR ( -- end during the range
EndTime > @StartTime
AND EndTime <= @EndTime
)
OR ( -- start before the range and end after it
StartTime < @StartTime
AND EndTime > @EndTime
)
)
AND
CASE
WHEN @ReservationId IS NULL THEN 1
WHEN ReservationId IS NOT NULL AND ReservationId = @ReservationId THEN 1
END = 1
首先,在您原来的 SQL 中,您使用的是 OR 而不是 AND,这会影响您的结果。
要整理 aircraftId、instructorId 和 reservationId 上的过滤器,您可以执行以下操作:
SELECT COUNT(*)
FROM AVMAN.Reservation
WHERE
ISNULL( @AircraftId, AircraftId ) = AircraftId
AND
ISNULL( @InstructorId, InstructorId ) = InstructorId
AND
ISNULL( @ReservationId, ReservationId ) = ReservationId
AND
( ( -- start during the range
StartTime >= @StartTime
AND StartTime < @EndTime
)
OR ( -- end during the range
EndTime > @StartTime
AND EndTime <= @EndTime
)
OR ( -- start before the range and end after it
StartTime < @StartTime
AND EndTime > @EndTime
)
)
ISNULL 基本上是在 AircraftId 不为空时将 AircraftId 与 @AircraftId 进行比较,而在 @AircraftId 为空时则与 AircraftId(显然始终相同)进行比较。