代码之家  ›  专栏  ›  技术社区  ›  user3247900

使用CASE-in-WHERE子句计算空参数

  •  1
  • user3247900  · 技术社区  · 7 年前

    是否有更好的方法获得以下信息?

    DECLARE @Desc VARCHAR(200) = ''
    
    SELECT [id],
           [Desc],
           [Col1],
           [Col2]
    FROM [dbo].[tbl]
    WHERE [Desc] LIKE CASE
                    WHEN @Desc LIKE ''
                         THEN [Desc]
                         ELSE '%'+ @Desc +'%'
                    END
    

    这允许在未定义参数时返回所有值(@Desc=“”),或返回值的子集(@Desc=“”)。

    4 回复  |  直到 7 年前
        1
  •  3
  •   Jayasurya Satheesh    7 年前

    使用OR运算符代替Case

    DECLARE @Desc VARCHAR(200) = ''
    
    SELECT [id],
           [Desc],
           [Col1],
           [Col2]
    FROM [dbo].[tbl]
    WHERE 
        (
            ISNULL(@Desc,'')=''
        )
        OR
        (
            ISNULL(@Desc,'')<>''
            AND
            [Desc] LIKE '%'+ @Desc +'%'
        )
    

    使用两种逻辑的执行计划差异

    使用案例

    enter image description here

    使用或

    enter image description here

        2
  •  2
  •   ColdSolstice    7 年前

    执行引擎最好在查询之前进行同样多的参数处理。

    DECLARE @Desc VARCHAR(200) = '';
    DECLARE @SelectAll bit;
    
    SET @SelectAll = CASE WHEN @Desc = '' THEN 1 ELSE 0 END;
    SET @Desc = CASE WHEN @Desc = '' THEN @Desc ELSE ('%' + @Desc + '%') END;
    
    
    SELECT [id],
           [Desc],
           [Col1],
           [Col2]
    FROM [dbo].[tbl]
    WHERE 
        (@SelectAll = 1)
            OR
        (@SelectAll = 0 AND [Desc] LIKE @Desc);
    

    如果您不介意代码重复,可以更进一步,使用If/ELSE分割两个单独的查询。

        3
  •  1
  •   paparazzo    7 年前

    如果使用null,则可以保存一些步骤

    declare @userId  int = null; 
    
    SELECT TOP 1000 [AuctionId]
          ,[UserId]
          ,[BiddingPrice]
          ,[DateTime]
      FROM [Test].[dbo].[Bid] 
      WHERE isnull(@userId, [UserId]) = [UserId];
    
        4
  •  1
  •   Zohar Peled    7 年前

    正如Aaron Bertrand所评论的,您当前的查询可以这样简单地编写:

    DECLARE @Desc VARCHAR(200) = ''
    
    SELECT [id],
           [Desc],
           [Col1],
           [Col2]
    FROM [dbo].[tbl]
    WHERE [Desc] LIKE '%'+ @Desc +'%' 
    

    自if起 @Desc 包含空字符串,结果为 [Desc] LIKE '%%' -所以所有记录 [Desc] 无论如何都将返回不为null。

    如果 @描述 可以传递为 null 使用 Coalesce 要转换 无效的 到空字符串:

    ...WHERE [Desc] LIKE '%'+ COALESCE(@Desc, '') +'%' 
    

    请注意,在这两个问题中 Desc 列包含 无效的 不会被退回。如果这是一个可为null的列,并且您还希望返回它所在的记录 无效的 以及 @描述 参数也为null或空,则应使用 OR :

    SELECT [id],
           [Desc],
           [Col1],
           [Col2]
    FROM [dbo].[tbl]
    WHERE [Desc] LIKE '%'+ @Desc +'%' 
    OR (COALESCE(@Desc, '') = '' AND [Desc] IS NULL)
    

    此外,请注意,这只是因为您使用 LIKE -是否应尝试使用不同的运算符(例如 = , < , > etc”)您应该使用 语法与其他答案类似。