可选的Where子句,不会影响性能

时间:2013-12-31 01:38:25

标签: sql sql-server sql-server-2008 tsql

我想知道是否有办法做这种查询(可选的where子句)而不对sql施加这样的负担。

 SELECT * 
 FROM TABLE 
 WHERE 
  Name = IsNull(@Name,Name) 
  AND (
       (@MinAge IS NULL AND @MaxAge IS NULL)
       OR
       (@MinAge IS NOT NULL AND @MaxAge IS NOT NULL AND Age BETWEEN @MinAge AND @MaxAge) 
      )

我知道我可以使用EXEC将其作为变量执行,并在需要时包含查询,如下所示:

   SET @sql = 'SELECT * FROM TABLE'
   IF(@Name IS NOT NULL) SET @sql = @sql + ' WHERE Name = ''+@Name+'''
   EXEC(@sql)

但我想避免这个选项^^^

我不知道SQL世界中的任何其他选项?

第一个查询会使SQL的负载成本超出所需的负担。

3 个答案:

答案 0 :(得分:1)

Erland Sommarskog的这篇文章是我所知道的最广泛的资源 Dynamic Search Conditions in T‑SQL

答案 1 :(得分:0)

我认为你有三种可能的选择:

OPTION RECOMPILE

建议服务器在每次执行期间重新编译查询。它应该能够检测NULL值并相应地进行优化。 显然,缺点是每次执行时都要重新编译。

OPTIMIZE FOR

告诉服务器优化参数集的查询。在那里,您确实只有一个执行计划,但由于不幸的第一次查询,您不会冒更改的风险。

写两次

输入IF语句并进行两次查询。 如果您有许多参数,这当然不能很好地扩展......

答案 2 :(得分:0)

当您执行 BETWEEN 时,您不必检查 NOT NULL ,如果是@MinAge,它将无法通过该条件或者@MaxAge为空。换句话说,您可以按如下方式重写WHERE子句......

WHERE Name = IsNull(@Name,Name) 
  AND (
        (@MinAge IS NULL AND @MaxAge IS NULL)
        OR
        (Age BETWEEN @MinAge AND @MaxAge) 
      )

我通常试图避免的另一个选项是使用if-else检查变量的状态,然后根据结果分支到两个单独的select语句中。换句话说......

IF @MinAge IS NULL AND @MaxAge IS NULL 
    SELECT <columnlist>
    FROM TABLE 

ELSE
    SELECT <columnlist>
    FROM TABLE
    WHERE Age BETWEEN @MinAge AND @MaxAge