【问题标题】:Conditional where clause?有条件的where子句?
【发布时间】:2013-09-11 09:30:33
【问题描述】:

我想应用条件 where 子句也就是说,如果我的 barcode 参数为空,那么我想获取所有记录,如果它带有值,那么我想只获取第二部分的匹配记录,我能够获取匹配的记录,但我坚持在空值的情况下获取所有记录,我尝试如下,

 SELECT item 
 FROM tempTable
 WHERE 
  ((ISNULL(@barcode,0)=1)
      // but this is not fetching all the records if barcode is null 
   OR
   ISNULL(@barcode,0!= 1 AND tempTable.barcode LIKE @barcode+'%'))
      //THis is working perfect 

所以任何帮助都会很棒

【问题讨论】:

  • ISNULL(@barcode,0!= 1 好像缺少括号

标签: sql sql-server sql-server-2008 where where-clause


【解决方案1】:

我可能误解了你的问题,但逻辑 OR 运算符可能会有所帮助:

SELECT item 
 FROM tempTable
 WHERE 
 @barcode IS NULL OR tempTable.barcode LIKE @barcode+'%'

如果@barcodeNULL,则返回所有记录,如果不是NULL,则返回所有满足条件LIKE @barcode+'%'的记录

重要

另外,请记住,使用 OR 运算符在与多个复杂条件 AND-ed 一起使用时可能会产生有趣的结果,并且没有正确括在大括号中:

<A> AND <B> AND <C> OR <D> AND <E> AND <F>

应该很可能实际上被表述为:

(<A> AND <B> AND <C>) OR (<D> AND <E> AND <F>)

记住,解析器不知道你想要实现什么,你必须正确地描述你的意图......

【讨论】:

    【解决方案2】:

    我认为您可以将其简化为:

      SELECT item 
     FROM tempTable
     WHERE @barcode IS NULL OR tempTable.barcode LIKE @barcode+'%'
    

    因此,当@barcode 为空时,您将获得所有内容 - 即不需要执行 where 的 Like 部分。如果@barcode 有一个值,那么 Like 将被执行。

    【讨论】:

    • 如果值可以是 0 或 null 并且您想要这些情况下的所有内容,只需将 where 更改为 WHERE isnull(@barcode,0) = 0 OR tempTable.barcode LIKE @barcode+'%'
    【解决方案3】:

    如果条形码字段不为空,那么这是我将使用的方法 -

    SELECT item 
    FROM tempTable
    WHERE barcode like isnull(@barcode, barcode) + '%'
    

    如果@barcode 为空,则返回所有记录,如果它不为空,则只返回匹配的记录。

    如果条形码字段可以为空,那么 -

    SELECT item 
    FROM tempTable
    WHERE isnull(barcode, '') like isnull(@barcode, isnull(barcode, '')) + '%'
    

    与第一个相同,但这里我们在进行比较之前将条形码字段中的空值转换为空白字符串。

    【讨论】:

      【解决方案4】:

      另一个答案和赏金的尝试

      declare @barcode nvarchar(10) -- chose nvarchar not necessarily should be nvarchar
      select @barcode= NULL
      --select @barcode='XYZ'
      if @barcode is null
      select item from temptable;
      else
      select item from temptable where temptable.barcode like @barcode+'%';
      

      【讨论】:

        【解决方案5】:

        如果我必须这样做,我会这样做

        SELECT item 
         FROM tempTable
         WHERE 
        ( ( ISNULL(@barcode,'') <> '')  AND ( tempTable.barcode LIKE @barcode+'%' ) )
        

        ( ISNULL(@barcode,'') &lt;&gt; '') 还会检查变量是否为空,那么它不应该返回任何内容。但是,如果您只是检查 null,那么当 @barcode 为空时,您将从 tempTable 中选择所有 item

        【讨论】:

          【解决方案6】:

          如果barcode 列不可为空,则可以大大简化查询。 这是基于模式 '%' 匹配 any 字符串的事实;甚至是一个空(即零长度)字符串。 因此,以下 WHERE 子句匹配 所有 记录:

          WHERE barcode LIKE '%'
          

          您可能会注意到,这与您用于过滤特定条形码上的记录的 WHERE 子句非常相似:

          WHERE barcode LIKE @barcode + '%'
          

          事实上,它们非常相似,我们不妨对这两种情况都使用一个 WHERE 子句;毕竟,'' + '%' 等于 '%'

          IF @barcode IS NULL SET @barcode = ''
          SELECT item FROM tempTable WHERE barcode LIKE @barcode + '%'
          

          还有一个更短的版本,它保留了@barcode 的原始值:

          SELECT item FROM tempTable WHERE barcode LIKE ISNULL(@barcode, '') + '%'
          

          如前所述,这仅适用于列 barcode 不可为空的情况。 如果列 barcode 可以为空(并且您真正对 barcode IS NULL 所在的记录感兴趣),那么以下查询可能适合您:

          SELECT item FROM tempTable
          WHERE ISNULL(barcode, '') LIKE ISNULL(@barcode, '') + '%'
          

          但是,这个版本有两个缺点:

          • 可能执行得更慢,因为查询优化器可能无法从列barcode 上的索引中受益。
          • 如果@barcode = '',则不仅匹配非空条码,还匹配barcode IS NULL的记录;这是否可以接受,取决于您。

          最后一个简化:您可能希望与外界达成共识,他们应该设置@barcode = '' 而不是NULL 来检索所有记录。然后你可以用@barcode替换ISNULL(@barcode, '')

          【讨论】:

            【解决方案7】:

            除了 ppeterka 的解决方案(这将导致索引/表扫描)之外,至少还有三个其他解决方案。如果@barcode 不为NULL,并且如果barcode 列上有索引,这些解决方案可以使用Index Seek

            解决方案#2:执行计划不被缓存和重用:

            SELECT item 
            FROM tempTable
            WHERE @barcode IS NULL OR tempTable.barcode LIKE @barcode+'%'
            OPTION(RECOMPILE);
            

            方案#3:执行计划被缓存(可选参数个数少时可以使用):

            IF @barcode IS NULL
                SELECT item 
                FROM tempTable;
            ELSE
                SELECT item 
                FROM tempTable
                WHERE tempTable.barcode LIKE @barcode+'%';
            

            方案#4:执行计划被缓存(可选参数数量多时可以使用):

            DECLARE @SqlStatement NVARCHAR(MAX);
            SET @SqlStatement = N'
            SELECT item 
            FROM tempTable
            WHERE 1=1 '
            + CASE WHEN @barcode IS NULL THEN N'' ELSE N'AND tempTable.barcode LIKE @pBarcode+''%''; ' END; 
            -- + CASE WHEN @anotherparam IS NULL THEN N'' ELSE 'AND ...' END ;
            
            EXEC sp_executesql @SqlStatement, N'@pBarcode VARCHAR(10)', @pBarcode = @barcode;
            

            注意:使用正确的类型和最大值。 @pBarcode 参数的长度/精度和比例。

            【讨论】:

            • 解决方案#3 & #4:[估计的]执行计划被缓存和重用。
            【解决方案8】:

            如果@barcode 为空

            开始

            从临时表中选择项目

            结束

            否则 SELECT item FROM tempTable where tempTable.barcode LIKE @barcode+'%'

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2015-05-15
              • 2014-09-30
              • 1970-01-01
              • 2018-02-06
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多