【问题标题】:Use CASE to conditionally add an AND condition to query使用 CASE 有条件地添加 AND 条件进行查询
【发布时间】:2020-01-31 17:02:10
【问题描述】:

我正在尝试创建一个存储过程,根据参数不是空字符串,应该将 AND 条件添加到查询中。如果参数为空字符串,则根本不应该添加 AND 条件。我希望匹配使用 LIKE 而不是“=”,如:

DECLARE @searchstring VARCHAR(50);

SET @searchstring = 'hang up';

SELECT *
FROM ContactLog
WHERE CREATED_DATE > '2020-01-01'
    AND Brief_Statement LIKE '%' + CASE 
        WHEN @searchstring != ''
            THEN @searchstring
        ELSE Brief_Statement
        END + '%'
    AND Log_Type = 'L';

SET @searchstring = '';

SELECT *
FROM ContactLog
WHERE CREATED_DATE > '2020-01-01'
    -- in this case, since @searchString is empty, I'd like to eliminate this next condition altogether
    AND Brief_Statement LIKE '%' + CASE 
        WHEN @searchstring != ''
            THEN @searchstring
        ELSE Brief_Statement
        END + '%'
    AND Log_Type = 'L'

我知道如果我使用“=”而不是 LIKE,我可以这样做...

SET @searchstring = '';

SELECT TOP 10 *
FROM ContactLog
WHERE CREATED_DATE > '2020-01-01'
    AND Brief_Statement = CASE 
        WHEN @searchstring != ''
            THEN @searchstring
        ELSE Brief_Statement
        END
    AND Log_Type = 'L'

但我不确定使用 LIKE 执行此操作的效果,并希望查询尽可能高效。

有什么好的方法可以做到这一点?

【问题讨论】:

  • dba.stackexchange.com/a/74466/2131 不要试图让一个查询适用于所有情况,因为它可能很糟糕。相反,使 where 子句动态以反映不同的搜索可能性。另外,要小心 SQL 注入
  • 当您搜索子字符串(带有前导通配符)时,它不会对性能产生太大影响。要么您返回与其他谓词匹配的所有行,要么您至少需要检查它们以查看它们是否与搜索字符串谓词匹配。它不会对读取的行产生影响
  • 根据ContacLog 的大小、结构以及最终您对数据的处理方式,将中间结果转储到临时表然后应用前导通配符可能会更好搜索。测试将证明您或数据库引擎对数据进行子集化是否会更有效

标签: sql-server


【解决方案1】:

你可以试试这个条件 where 子句。我已经简化了您在过滤条件中提供的 case 语句。

样本数据在应用时会更有效,如您所说,您可以尝试使用 like 运算符代替 equal to 运算符。

这是给你的additional reference

SELECT TOP 10 *
FROM ContactLog
WHERE CREATED_DATE > '2020-01-01'
    AND @searchstring = ''
    OR (
        @searchstring <> ''
        AND Brief_Statement = @searchstring
        )
    AND Log_Type = 'L'

这里是演示

Create table TestTable (Id int, Name varchar(10))
Insert into TestTable Values (1, 'A'), (2, 'B'), (3, 'C'), (4, 'D'), (5, 'E')

Select * from TestTable --Selecting all the records.

declare @searchstring varchar(5) = ''; -- Without filter criteria passing.
Select * from TestTable
where 1 = 1
AND @searchstring = ''
    OR (
        @searchstring <> ''
        AND Name = @searchstring
        )

set  @searchstring = 'D' --By passing filter criteria.
Select * from TestTable
where 1 = 1
AND @searchstring = ''
    OR (
        @searchstring <> ''
        AND Name = @searchstring
        )

Demo Link

【讨论】:

  • 我最终根据您的回答使用了这个:和 (@searchstring = '' or (@searchstring != '' and Brief_Statement like + '%' + @searchstring + '%')) 谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-28
  • 1970-01-01
  • 2010-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多