【问题标题】:SQL Server 2008, different WHERE clauses with one querySQL Server 2008,一个查询的不同 WHERE 子句
【发布时间】:2015-11-21 02:02:47
【问题描述】:

我有一个存储过程,它采用相同的列但具有不同的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(条件)中,其中 WHERE 子句根据传入变量的参数而变化。

我是否必须为每个 if 中的每个条件一遍又一遍地写整个字符串?

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

【问题讨论】:

  • 你的 Ifs 和参数在哪里?
  • 标记为迁移到 dba.stackexchange.com,因为这将更适合该问题。
  • 您应该选择以下答案之一来结束问题。这个问题被问了很多,复制者可以在这里指出。

标签: sql sql-server-2008 tsql


【解决方案1】:

你不必这样做,你可以通过做类似的事情来解决它

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

虽然与第一个查询等效,但应该会产生更好的性能,因为它会得到更好的优化。

【讨论】:

  • 如果根据经验你说重复查询不是“坏习惯”,那么我相信。这也是我的解决方案。我想知道老计时器是如何处理这个问题的,我对 SQL SERVER 有点陌生,我已经习惯了尽可能多地尝试优化代码,这是一个合理的问题,谢谢你们的回答. :)
【解决方案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 ...';

如果您启用了服务器设置“针对临时查询进行优化”,这可能会更好。

【讨论】:

    【解决方案3】:

    我可能会坚持重复整个 SQL 语句,但过去曾使用过这种方法...

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

    不是特别可读,如果执行计划很慢,您​​将不得不检查执行计划,但它可以防止您重复代码。

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        【解决方案5】:

        就像 SQL 中的大多数东西一样:这取决于。这里有一些考虑。

        • 不同的 WHERE 是否会导致显着不同的查询 执行计划被索引的列之一,但不是另一列 两个
        • 查询是否可能随时间改变:即客户 需要其他列的要求
        • WHERE 是否可能变成 4, 然后是 8 个,然后是 16 个等选项。

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

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

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

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

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

        【讨论】:

          【解决方案6】:

          我会这样: 其中 8 = 案例@参数 当 1 时 1 列 WHEN 2 THEN 列 2 . . .

          【讨论】:

          • 您能否详细说明您的解决方案,好吗?据我了解,整个 WHERE 子句可能有所不同。
          猜你喜欢
          • 2014-03-30
          • 1970-01-01
          • 1970-01-01
          • 2013-12-06
          • 1970-01-01
          • 2023-03-13
          • 2014-11-04
          • 1970-01-01
          相关资源
          最近更新 更多