SQL Server 2008,具有一个查询的不同WHERE子句

时间:2012-06-20 16:48:39

标签: sql sql-server-2008 tsql

我有一个存储过程,它使用相同的列,但具有不同的WHERE子句。

像这样的东西。

SELECT
     alarms.startt, alarms.endt, clients.code, clients.Plant,
     alarms.controller, alarmtype.atype, alarmstatus.[text]
FROM alarms
INNER JOIN clients ON alarms.clientid = clients.C_id 
INNER JOIN alarmstatus ON alarms.statusid = alarmstatus.AS_id
INNER JOIN alarmtype ON alarms.typeid = alarmtype.AT_id

我在3 if if(条件)中放入相同的查询,其中WHERE子句根据变量中传递的参数而变化。

我是否必须在每个if?

中为每个条件反复编写整个字符串

或者我可以优化它一次,唯一会改变的是WHERE子句吗?

6 个答案:

答案 0 :(得分:2)

你不必这样做,你可以通过做

这样的事情来绕过它
SELECT  *
FROM    [Query]
WHERE   (@Parameter = 1 AND Column1 = 8)
OR      (@Parameter = 2 AND Column2 = 8)
OR      (@Parameter = 3 AND Column3 = 8)

然而,仅仅因为你可以做某事,并不意味着你应该做。较不详细的SQL并不意味着更好的性能,因此请使用以下内容:

IF @Parameter = 1
    BEGIN
        SELECT  *
        FROM    [Query]
        WHERE   Column1 = 8
    END
ELSE IF @Parameter = 2
    BEGIN
        SELECT  *
        FROM    [Query]
        WHERE   Column2 = 8
    END
ELSE IF @Parameter = 3
    BEGIN
        SELECT  *
        FROM    [Query]
        WHERE   Column3 = 8
    END

虽然与第一个查询相当,但应该会产生更好的性能,因为它会更好地进行优化。

答案 1 :(得分:2)

如果您执行以下操作,则可以避免重复代码:

WHERE (col1 = @var1 AND @var1 IS NOT NULL)
OR ...
OPTION RECOMPILE;

您还可以通过数据库的参数化设置(简单与强制)对此行为产生一些影响。

由于参数嗅探而避免重复代码并避免次优计划的事情是使用动态SQL:

DECLARE @sql NVARCHAR(MAX) = N'SELECT ...';
IF @var1 IS NOT NULL
  SET @sql = @sql + ' WHERE ...';

如果您启用了“针对即席查询优化”的服务器设置,这可能会更好。

答案 2 :(得分:1)

我可能会坚持重复整个SQL语句,但过去已经采用了这个...

WHERE (@whichwhere=1 AND mytable.field1=@id)
  OR (@whichwhere=2 AND mytable.field2=@id)
  OR (@whichwhere=3 AND mytable.field3=@id)

不是特别易读,如果执行计划很慢,你必须检查执行计划,但它会阻止你重复代码。

答案 3 :(得分:1)

因为没有人提出这个建议。您可以将原始查询放在视图中,然后使用不同的WHERE子句访问该视图。

为了提高性能,如果您知道WHERE子句中常用的列,则甚至可以向视图添加索引(请查看http://msdn.microsoft.com/en-us/library/dd171921(v=sql.100).aspx)。

答案 4 :(得分:0)

与SQL中的大多数事情一样:它取决于。这里有一些考虑因素。

  • 不同的WHERE会导致不同的查询 执行计划,例如其中一列索引但不是另一列 2
  • 查询是否可能随时间而变化:即客户 需要其他专栏的要求
  • WHERE可能变为4, 那么8,然后是16等选项。

一种方法是将不同的procs执行到临时表中。然后每个proc都有自己的查询计划。

另一种方法是使用动态SQL,再次为每个“查询”分配自己的计划。

第三个方法是编写一个为每个选项生成SQL的应用程序,这可以是存储过程或sql字符串。

然后有一个数据集并针对它进行测试驱动开发(对于每种方法都是如此)。

最终,最好的学习解决方案可能是 a)阅读SQL Kalen Delaney Inside SQL是一位公认的专家。 b)根据您自己的数据测试您自己的解决方案

答案 5 :(得分:0)

我会这样: 在哪里8 = CASE @parameter 当1那么Column1 当2那么Column2 。 。