如果已找到结果集,则忽略其他结果

Ignore other results if a resultset has been found

首先,以这个片段为例:

SELECT * 
FROM StatsVehicle 
WHERE ((ReferenceMakeId = @referenceMakeId)
 OR @referenceMakeId IS NULL)

如果变量@referenceMakeId 不为空,这将获取并过滤记录,如果为空,将获取所有记录。换句话说,如果@referenceMakeId 不为空,它会考虑第一个。

我想对此添加进一步的限制,我该如何实现?

例如

(ReferenceModelId = @referenceModeleId) OR
(
    (ReferenceMakeId = @referenceMakeId) OR
    (@referenceMakeId IS NULL)
)

如果@referenceModelId不为null,则只需要通过ReferenceModelId进行过滤,忽略其中的其他语句。如果我真的这样做,它 returns 所有记录。有什么办法可以实现这样的事情吗?

也许是这样的?

SELECT * FROM StatsVehicle WHERE 
( 
    -- Removed the following, as it's not clear if this is beneficial
    -- (@referenceModeleId IS NOT NULL) AND 
    (ReferenceModelId = @referenceModeleId)
) OR
(@referenceModeleId IS NULL AND 
 (
    (ReferenceMakeId = @referenceMakeId) OR
    (@referenceMakeId IS NULL)
 )
)

这应该可以解决问题。

SELECT * FROM StatsVehicle 
WHERE ReferenceModelId = @referenceModeleId OR
(
@referenceModeleId IS NULL AND 
    (
    @referenceMakeId IS NULL OR
    ReferenceMakeId = @referenceMakeId
    )
)

但是,您应该注意,这种类型的查询(称为包罗万象的查询)的效率往往低于为每个案例编写一个查询。

这是因为 SQL 服务器将缓存第一个查询计划,该计划对于其他参数可能不是最优的。

您可能需要考虑使用 OPTION (RECOMPILE) query hint,或将存储过程分解为多个部分,每个部分将处理特定条件(即一个 select 用于空变量,一个 select 表示非空)。

有关详细信息,请阅读 this article

If @referenceModelId is not null, it will only need to filter by ReferenceModelId, and ignore the other statements inside it. If I actually do this as such, it returns all the records. Is there anything that can be done to achieve such a thing?

你可以考虑使用CASE来获得良好的短路机制

WHERE
    CASE 
        WHEN @referenceModelId is not null AND ReferenceModelId = @referenceModeleId THEN 1
        WHEN @referenceMakeId is not null AND ReferenceMakeId = @referenceMakeId  THEN 1
        WHEN @referenceModelId is null AND @referenceMakeId is null THEN 1
        ELSE 0
    END = 1