Iro*_*fin 16 t-sql sql-server case query-optimization where-clause
我一直在争夺这一个.我有一个存储过程,它接受3个用于过滤的参数.如果传入特定值,我想对其进行过滤.如果传入-1,请全部给我.
我试过以下两种方式:
第一种方式:
SELECT field1, field2...etc  
FROM my_view  
WHERE  
parm1 = CASE WHEN @PARM1= -1 THEN parm1  ELSE @PARM1 END  
AND parm2 = CASE WHEN @PARM2 = -1 THEN parm2  ELSE @PARM2 END  
AND parm3 = CASE WHEN @PARM3 = -1 THEN parm3  ELSE @PARM3 END
第二种方式:
SELECT field1, field2...etc  
FROM my_view  
WHERE  
(@PARM1 = -1 OR parm1 = @PARM1)  
AND (@PARM2 = -1 OR parm2 = @PARM2)  
AND (@PARM3 = -1 OR parm3 = @PARM3)  
我读到某处,第二种方式会短路,如果是真的话,永远不会评估第二种方式.我的DBA说它强制进行表扫描.我还没有验证这一点,但在某些情况下似乎运行速度较慢.
此视图选择的主表有大约150万条记录,并且视图继续加入大约15个其他表以收集大量其他信息.
这两种方法都很慢......把我从瞬间带到2-40秒的任何地方,这在我的情况下是完全不可接受的.
是否有更好的方法不涉及将其分解为特定vs -1的每个单独案例?
任何帮助表示赞赏.谢谢.
我读到某处,第二种方式会短路,如果是真的话,永远不会评估第二种方式.我的DBA说它强制进行表扫描.
你读错了; 它不会短路.你的DBA是对的; 它不能很好地与查询优化器一起使用,并可能强制进行表扫描.
第一个选择就是它一样好.您可以选择使用过滤器列的每个可能组合来动态sql或长存储过程,以便获得独立的查询计划.您也可以尝试使用"WITH RECOMPILE"选项,但我认为它不会对您有所帮助.
如果您运行的是SQL Server 2005或更高版本,则可以使用IF使用正确的WHERE创建多个版本的查询,以便可以使用索引.每个查询计划都将放在查询缓存中.
另外,这是一篇关于这个主题的非常全面的文章:
Erland Sommarskog在T-SQL中的动态搜索条件
它涵盖了尝试使用多个可选搜索条件编写查询的所有问题和方法
这是目录:
  Introduction
      The Case Study: Searching Orders
      The Northgale Database
   Dynamic SQL
      Introduction
      Using sp_executesql
      Using the CLR
      Using EXEC()
      When Caching Is Not Really What You Want
   Static SQL
      Introduction
      x = @x OR @x IS NULL
      Using IF statements
      Umachandar's Bag of Tricks
      Using Temp Tables
      x = @x AND @x IS NOT NULL
      Handling Complex Conditions
   Hybrid Solutions – Using both Static and Dynamic SQL
      Using Views
      Using Inline Table Functions
   Conclusion
   Feedback and Acknowledgements
   Revision History