高效的查询设计,包括可空参数

时间:2018-01-08 08:15:09

标签: sql sql-server performance join

使用:MS SQL SERVER 2008R2至2016

我有一个存储过程(下面的简化版本),它返回按几个参数中的任何一个过滤的产品列表。我返回的数据仅来自主表(Products),但可以通过任何其他表中的交叉引用数据进行过滤。

下面的代码将起作用,但是如果没有为连接提供参数,则效率明智,服务器仍然会获得链接到该表的效率,即使数据意味着不需要过滤。

我可以在动态sql中构建它,并根据参数添加连接,但我尽量避免动态 - 总是难以维护。

有没有人有他们使用过或想过的更好的解决方案?我确实有几个工作选项,但看看代码我觉得必须有更好的选择。

非常感谢。

CREATE PROC FilteredProducts
    @CatalogueID INT = NULL
,   @ManufacturerID INT = NULL
,   @BrandID INT = NULL
AS
    BEGIN
        SELECT  Products.*
        FROM    Products P
        JOIN    Catalogue C ON P.ID = C.ProductID
                               AND (@CatalogueID IS NULL
                                    OR C.ID = @CatalogueID
                                   )
        JOIN    Manufacturers M ON P.ID = M.Products_ID
                                   AND (@ManufacturerID IS NULL
                                        OR M.ID = @ManufacturerID
                                       )
        JOIN    Brands B ON P.ID = B.Products_ID
                            AND (@BrandID IS NULL
                                 OR B.ID = @BrandID
                                )

    END

编辑:

添加了代码示例

DECLARE @InstockOnly AS BIT = 0

SELECT  AP.*
FROM    ABCD.AllowedProducts AP
JOIN    ABCD.DatabaseStockLevels DSL ON DSL.ProductGUID = AP.ProductGUID
                                        AND (@InstockOnly = 0
                                             OR DSL.StockLevel > 0
                                            )
OPTION  (RECOMPILE)

当执行上面的代码以按库存级别进行特定过滤时,实际执行计划显示尽管InstockOnly = 0,但仍会评估连接。尽管我的数据是1对1关系,但SQL Server不知道,所以如果存在1对多关系,则执行连接。虽然选项(重新编译)确实简化了连接,但我正在寻找一种完全删除连接的方法。

0 个答案:

没有答案