【问题标题】:How to include a conditional OR statement in the SQL WHERE clause如何在 SQL WHERE 子句中包含条件 OR 语句
【发布时间】:2021-04-25 09:14:02
【问题描述】:

在我的 SQL 语句中,如果 Type 的值等于“T”,那么我想添加一个条件 OR 子句,如下所示。否则,将没有 OR 子句

if type not equal to 'T':
    select customerid, type from customer
    where cityid = '20' 

if type is equal to 'T'
    select customerid, type from customer
    where cityid = '20' OR cityid = '5'

【问题讨论】:

  • 旁白:cityid 真的是字符串吗?您的代码将其与字符串 ('20') 而非 int (20) 值进行比较。
  • 是的,cityid 是一个字符串。
  • type是表中的列还是代码中的变量(@type)?
  • @Kim 以下答案之一是否解决了您的问题?如果是这样,请考虑接受它。如果没有,请向我们提供更多信息。

标签: sql sql-server tsql logical-operators


【解决方案1】:

使用布尔逻辑:

select customerid, type from customer
where cityid = '20' or
      (cityid = '5' and type = 'T')

我建议您避免在where 子句中使用case 表达式。它们阻碍优化。

【讨论】:

    【解决方案2】:

    看起来你正在重构一个存储过程。

    假设type 是存储过程变量或参数,而不是customer 表中的列,我会这样表述:

    select c.customerid,
           c.type
    from customer c
    where 1 = case coalesce( @type, '' )
                when 'T' then case when c.cityid in ('20', '5') then 1 else 0 end
                else          case when c.cityid in ('20'     ) then 1 else 0 end
              end
    

    针对@type 的测试被包装在coalesce() 函数中,因为null 未通过任何测试,除了显式测试无效。

    我在这里也使用了case 表达式,因为它使事情更加表格化,并且当您需要为@type 为“Z”时添加新案例时.. . 这只是一个额外的when 子句。并且避免了andor之间的运算符优先级可能引起的混淆。

    【讨论】:

    • 何时将case 语句 添加到 TSQL?我只熟悉您的代码使用的case 表达式
    • Nicholas,我要重构的不是存储过程。我们有几个我必须使用的疯狂的遗留 SQL 表达式。
    • 已为您修复。 :)
    【解决方案3】:

    首先假设你写type的地方是@type

    您始终可以使用 OR 组合这种类型的逻辑,例如

    select customerid, @type
    from customer
    where
    -- Condition from first branch
    (@type != 'T' and cityid = '20')
    -- Condition from second branch
    or (@type = 'T' and (cityid = '5' or cityid = '20'));
    

    对括号格外小心,以确保获得所需的逻辑。

    注意:Operator PrecedenceANDOR 之前评估,因此是括号。

    这可以简化为:

    select customerid, @type
    from customer
    where cityid = '20'
    or (
        cityid = '5' and @type = 'T'
    );
    

    但是 OR 有一个导致性能问题的讨厌习惯,如果发生这种情况,您可以使用 union all 代替,例如

    select customerid, @type
    from customer
    where @type != 'T' and cityid = '20'
    
    union all
    
    select customerid, @type
    from customer
    where @type = 'T' and (cityid = '5' or cityid = '20');
    

    其他人建议在 where 子句中使用 case,但这样做可能会导致它变得不可分割,即无法使用索引,而且在我看来它更难阅读。它是学习使用复杂逻辑表达式的最佳 IMO。

    【讨论】:

      【解决方案4】:

      您可以使用 case 语句。将每个“何时”视为您的 if 语句;之后,您可以添加 where 语句逻辑。

      SELECT
          customerid,
          type
      FROM customer
      WHERE 
          1 = CASE
                  WHEN type <> 'T' AND cityid = '20' THEN 1 -- not equal to 'T'
                  WHEN type = 'T' AND (cityid = '20' OR cityid = '5') THEN 1 -- type is equal to 'T'
                  ELSE 0 
              END
      

      【讨论】:

      • 与实际逻辑相比,使用 case 表达式 有什么优势?它增加了一层复杂性,并可能影响性能。
      • @DaleK,如果查询更复杂并且唯一的区别是 If 语句部分,我们将复制代码两次。因此,通过将其设为 where 语句,我们可以使代码更具可读性。确实,它可能会妨碍性能;如果 case 语句表达式足够简单,那么性能影响可能可以忽略不计。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-26
      • 1970-01-01
      • 1970-01-01
      • 2011-08-21
      • 1970-01-01
      • 2012-11-18
      相关资源
      最近更新 更多