SQL IN通配符

时间:2019-02-06 00:47:44

标签: sql-server tsql

我有一个使用IN过滤器的查询,并且工作正常。我想知道是否有 就像通配符一样,不会过滤任何内容

<html> 
   <body>   
      <a href="https://www.w3schools.com/tags/tag_img.asp">
          <img class="img" src="https://upload.wikimedia.org/wikipedia/commons/4/49/LACMTA_Square_Orange_Line.svg" alt="image at bottom">
      </a>
   </body>
</html>

上面的方法按需要工作,但是如果我不想按任何内容过滤并返回全部,该怎么办。我知道我可以创建第二个查询并删除IN子句,但是如果可能的话,从逻辑上来说,如果我可以检查是否存在过滤器值并且如果不存在过滤器值,则将其替换为通配符char

会更好。

4 个答案:

答案 0 :(得分:1)

IN运算符不允许匹配通配符或部分值。实际上,它只是OR逻辑运算符链的语法糖

此查询:

SELECT 1 FROM SomeTable AS T
WHERE T.Column IN (1, 2, 3, 4)

与以下内容完全相同:

SELECT 1 FROM SomeTable AS T
WHERE 
    T.Column = 1 OR
    T.Column = 2 OR
    T.Column = 3 OR
    T.COlumn = 4

这就是为什么将NULL值和NOT IN列表一起使用会使所有逻辑结果变为UNKNOWN(因此被解释为false并且从不返回任何记录)的原因:

SELECT 1 FROM SomeTable AS T
WHERE T.Column NOT IN (1, 2, NULL, 4)

将会是:

SELECT 1 FROM SomeTable AS T
WHERE 
    NOT(
        T.Column = 1 OR
        T.Column = 2 OR
        T.Column = NULL OR      -- Always resolve to UNKNOWN (handled as false for the whole condition)
        T.COlumn = 4
        )

您可以通过几种选择有条件地应用IN之类的过滤器:

  • 在其他情况下使用OR

    DECLARE @ApplyInFilter BIT = 0
    
    SELECT 1 FROM SomeTable AS T
    WHERE 
        (@ApplyInFilter = 1 AND T.Column IN (1, 2, 3, 4)) OR
        @ApplyInFilter = 0
    
  • 完全避免查询(必须重复整个语句):

    DECLARE @ApplyInFilter BIT = 0
    
    IF @ApplyInFilter = 1
    BEGIN
        SELECT 1 FROM SomeTable AS T
        WHERE 
            T.Column IN (1, 2, 3, 4)
    END
    ELSE
    BEGIN
        SELECT 1 FROM SomeTable AS T
    END
    
  • 使用动态SQL有条件地省略过滤器:

    DECLARE @ApplyInFilter BIT = 0
    
    DECLARE @DynamicSQL VARCHAR(MAX) = '
        SELECT 1 FROM SomeTable AS T '
    
    IF @ApplyInFilter = 1
        SET @DynamicSQL += ' WHERE T.Column IN (1, 2, 3, 4) '
    
    EXEC (@DynamicSQL)
    

不幸的是,如果您打算拥有多个条件过滤器,最好的方法是使用动态SQL。这将是最难编写的代码,但性能最佳(有一些警告)。请阅读George的Menoutis链接,以充分了解每种方法的利弊。

答案 1 :(得分:0)

您可以利用不存在来获得所需的结果。根据我的理解,如果您有一个像Tom这样的名字,那么您只想要该行,如果您不想,则希望显示所有其他行。

 select 1 as ID, 'Tom' as Name into #temp 
 union all 
 select 2 as ID, 'Ben' as Name union all 
 select 3 as ID, 'Kim' as Name 
 union all 
 select 4 as ID, 'Jim' as Name  

 This query will check if Tom exists then display only that row if not display all. 

 select * from #temp   
 where name = 'TOm'  or not exists (select 1 from #temp where name = 'Tom') 

 Result from above query: 

   ID Name 
   1  Tom 

通过删除Tom记录所在的行来对其进行测试。

Delete from #temp 
where name = 'Tom' 

如果运行相同的查询,则会得到以下结果。

select * from #temp 
where name = 'TOm' or not exists (select 1 from #temp where name = 'Tom') 

 ID Name
 2  Ben
 3  Kim
 4  Jim

答案 2 :(得分:0)

正如Dale Burrell所说,实现动态搜索条件(正是您的问题所在)的快速方法是将代码放入:

....and field=values or @searchThisField=0

另一种解决方案是动态sql。

我认为Erland Sommarskog's article是分析此特定主题的缩影。

答案 3 :(得分:0)

发出两个请求。这两个查询的性能将比单个通用查询的性能更好。您可以比较这些查询的执行计划。