【问题标题】:How do I perform an IF...THEN in an SQL SELECT?如何在 SQL SELECT 中执行 IF...THEN?
【发布时间】:2010-09-08 23:19:48
【问题描述】:

如何在SQL SELECT 语句中执行IF...THEN

例如:

SELECT IF(Obsolete = 'N' OR InStock = 'Y' ? 1 : 0) AS Saleable, * FROM Product

【问题讨论】:

  • 你可能想看看这个link。关于:SQL WHERE 子句:避免 CASE,使用布尔逻辑
  • @Somebody:不是很相关,因为文章讨论了使用逻辑重写规则将蕴含转换为析取。线索是“逻辑”一词,即解析为真或假的东西,不适用于投影。 TL;DR 文章适用于WHERECHECK,但不适用于SELECT
  • @MartinSmith 的回答是最优雅的 - 在 SQL 2012+ 中使用 IIF。

标签: sql sql-server tsql if-statement case


【解决方案1】:

CASE 语句最接近 SQL 中的 IF,所有版本的 SQL Server 都支持。

SELECT CAST(
             CASE
                  WHEN Obsolete = 'N' or InStock = 'Y'
                     THEN 1
                  ELSE 0
             END AS bit) as Saleable, *
FROM Product

如果您希望结果为布尔值,您只需要使用CAST 运算符。如果您对int 感到满意,则可以这样做:

SELECT CASE
            WHEN Obsolete = 'N' or InStock = 'Y'
               THEN 1
               ELSE 0
       END as Saleable, *
FROM Product

CASE 语句可以嵌入到其他CASE 语句中,甚至可以包含在聚合中。

SQL Server Denali (SQL Server 2012) 添加了IIF 语句,这在access 中也可用(由Martin Smith 指出):

SELECT IIF(Obsolete = 'N' or InStock = 'Y', 1, 0) as Saleable, * FROM Product

【讨论】:

  • 请注意,不要在使用案例时将您的条件括在括号中。花了很多时间才意识到这一点:)
  • 别忘了END
  • @ReeveStrife 仅限 iif SQL Server 2012+
  • @ArchanMishra 你好,Archan,你能解释一下为什么你不应该附上你的条件吗?
  • 谨防 CASE/IIF 的肮脏秘密:sqlperformance.com/2014/06/t-sql-queries/…
【解决方案2】:

case 陈述在这种情况下是你的朋友,它采用以下两种形式之一:

简单案例:

SELECT CASE <variable> WHEN <value>      THEN <returnvalue>
                       WHEN <othervalue> THEN <returnthis>
                                         ELSE <returndefaultcase>
       END AS <newcolumnname>
FROM <table>

扩展案例:

SELECT CASE WHEN <test>      THEN <returnvalue>
            WHEN <othertest> THEN <returnthis>
                             ELSE <returndefaultcase>
       END AS <newcolumnname>
FROM <table>

您甚至可以将 case 语句放在 order by 子句中,以实现真正花哨的排序。

【讨论】:

  • 我知道这是旧的,但我认为应该注意的是,您可以在 END 之后添加 AS Col_Name 来命名结果列
  • 总觉得第二个比较简单。
  • 同意,我几乎总是最终使用扩展的 case 语句,因为我想要测试的条件总是比一个变量本身更复杂。我也觉得它更容易阅读。
  • 对这两种情况都有很好的解释,有或没有变量。使用变量,条件需要满足 case 语句之后的变量与您的条件所基于的变量之间的相等性,没有变量您可以添加一个自给自足的条件进行测试。
  • 我不认为这是个人偏好选择一个而不是另一个......它的用例:D
【解决方案3】:

从 SQL Server 2012 开始,您可以为此使用 IIF function

SELECT IIF(Obsolete = 'N' OR InStock = 'Y', 1, 0) AS Salable, *
FROM   Product

这实际上只是编写CASE 的一种简写方式(尽管不是标准 SQL)。

与扩展的CASE 版本相比,我更喜欢简洁。

IIF()CASE 都解析为 SQL 语句中的表达式,并且只能在明确定义的地方使用。

CASE 表达式不能用于控制执行流程 Transact-SQL 语句、语句块、用户定义的函数和 存储过程。

如果这些限制不能满足您的需求(例如,需要根据某些条件返回不同形状的结果集),那么 SQL Server 也有一个过程化的IF 关键字。

IF @IncludeExtendedInformation = 1
  BEGIN
      SELECT A,B,C,X,Y,Z
      FROM   T
  END
ELSE
  BEGIN
      SELECT A,B,C
      FROM   T
  END

Care must sometimes be taken to avoid parameter sniffing issues with this approach however.

【讨论】:

  • 如果你想要一个 IF.. then SQL 语句,这应该是答案。
【解决方案4】:

你可以在The Power of SQL CASE Statements中找到一些很好的例子,我认为你可以使用的语句是这样的(来自4guysfromrolla):

SELECT
    FirstName, LastName,
    Salary, DOB,
    CASE Gender
        WHEN 'M' THEN 'Male'
        WHEN 'F' THEN 'Female'
    END
FROM Employees

【讨论】:

  • 请参阅:meta.stackexchange.com/questions/103053/… 进行有趣的讨论。我提供的两个链接确实添加了额外的上下文,我支持。
  • 参考真的很有用,如果有更多详细信息,强烈推荐
【解决方案5】:

使用案例。像这样。

SELECT Salable =
        CASE Obsolete
        WHEN 'N' THEN 1
        ELSE 0
    END

【讨论】:

    【解决方案6】:
    SELECT  
    (CASE 
         WHEN (Obsolete = 'N' OR InStock = 'Y') THEN 'YES'
                                                ELSE 'NO' 
     END) as Salable
    , * 
    FROM Product
    

    【讨论】:

      【解决方案7】:

      Microsoft SQL Server (T-SQL)

      select 中,使用:

      select case when Obsolete = 'N' or InStock = 'Y' then 'YES' else 'NO' end
      

      where 子句中,使用:

      where 1 = case when Obsolete = 'N' or InStock = 'Y' then 1 else 0 end
      

      【讨论】:

      • 你为什么不直接做 where Obsolete = 'N' or InStock = 'Y' 并把 where 切成两半
      【解决方案8】:

      this link,我们可以理解T-SQL中的IF THEN ELSE

      IF EXISTS(SELECT *
                FROM   Northwind.dbo.Customers
                WHERE  CustomerId = 'ALFKI')
        PRINT 'Need to update Customer Record ALFKI'
      ELSE
        PRINT 'Need to add Customer Record ALFKI'
      
      IF EXISTS(SELECT *
                FROM   Northwind.dbo.Customers
                WHERE  CustomerId = 'LARSE')
        PRINT 'Need to update Customer Record LARSE'
      ELSE
        PRINT 'Need to add Customer Record LARSE' 
      

      这对 T-SQL 来说还不够好吗?

      【讨论】:

      • 这不是请求者想要的,但知道您可以在 select 语句之外使用 if 语句非常有用。
      • EXISTS 很好,因为如果找到项目,它就会退出搜索循环。 COUNT 一直运行到表行的末尾。与问题无关,但要知道一些事情。
      【解决方案9】:
       SELECT
         CASE 
            WHEN OBSOLETE = 'N' or InStock = 'Y' THEN 'TRUE' 
            ELSE 'FALSE' 
         END AS Salable,
         * 
      FROM PRODUCT
      

      【讨论】:

        【解决方案10】:

        SQL Server 中的简单 if-else 语句:

        DECLARE @val INT;
        SET @val = 15;
        
        IF @val < 25
        PRINT 'Hi Ravi Anand';
        ELSE
        PRINT 'By Ravi Anand.';
        
        GO
        

        SQL Server 中的嵌套 If...else 语句 -

        DECLARE @val INT;
        SET @val = 15;
        
        IF @val < 25
        PRINT 'Hi Ravi Anand.';
        ELSE
        BEGIN
        IF @val < 50
          PRINT 'what''s up?';
        ELSE
          PRINT 'Bye Ravi Anand.';
        END;
        
        GO
        

        【讨论】:

        • 迟到了,但它可以在SELECT 内使用吗?
        【解决方案11】:

        使用 CASE 语句:

        SELECT CASE
               WHEN (Obsolete = 'N' OR InStock = 'Y')
               THEN 'Y'
               ELSE 'N'
        END as Available
        
        etc...
        

        【讨论】:

          【解决方案12】:

          在 SQL Server 2012 中添加了一个新功能 IIF(我们可以简单地使用):

          SELECT IIF ( (Obsolete = 'N' OR InStock = 'Y'), 1, 0) AS Saleable, * FROM Product
          

          【讨论】:

          • 这个答案重复了几年前already provided in the answer by Martin Smith 的内容(细节较少)。
          • @jk7 这是这个问题的第一个答案。
          • 不是我看到的。它说您的答案发布于 16 年 4 月 26 日,而 Martin 的答案发布于 11 年 7 月 20 日。
          【解决方案13】:

          使用纯位逻辑:

          DECLARE @Product TABLE (
              id INT PRIMARY KEY IDENTITY NOT NULL
             ,Obsolote CHAR(1)
             ,Instock CHAR(1)
          )
          
          INSERT INTO @Product ([Obsolote], [Instock])
              VALUES ('N', 'N'), ('N', 'Y'), ('Y', 'Y'), ('Y', 'N')
          
          ;
          WITH cte
          AS
          (
              SELECT
                  'CheckIfInstock' = CAST(ISNULL(NULLIF(ISNULL(NULLIF(p.[Instock], 'Y'), 1), 'N'), 0) AS BIT)
                 ,'CheckIfObsolote' = CAST(ISNULL(NULLIF(ISNULL(NULLIF(p.[Obsolote], 'N'), 0), 'Y'), 1) AS BIT)
                 ,*
              FROM
                  @Product AS p
          )
          SELECT
              'Salable' = c.[CheckIfInstock] & ~c.[CheckIfObsolote]
             ,*
          FROM
              [cte] c
          

          working demo: if then without case in SQL Server

          首先,您需要针对选定的条件计算truefalse 的值。来了两个NULLIF

          for true: ISNULL(NULLIF(p.[Instock], 'Y'), 1)
          for false: ISNULL(NULLIF(p.[Instock], 'N'), 0)
          

          组合在一起给出 1 或 0。接下来使用 bitwise operators

          这是最WYSIWYG的方法。

          【讨论】:

          • -1 用于代码混淆。说真的,这与所见即所得的距离差不多!红红的难以理解的混乱,如果我不得不处理你的代码,我会整天诅咒......对不起:-/
          • @Heliac 将 cte 部分放入 View 中,您将永远看不到混乱。对于冗长而复杂的 AND,OR,NOT 它比 CASE 更具可读性(当然是 cte 之外的那部分)。
          • 我已经给它一个整洁的 +1,一旦它在一个 cte 中,但请注意这个问题的答案目前是错误的。你需要一个'|'不是“&”。
          • 完全同意@Heliac。虽然它在语法上是正确的并且工作正常,但它不容易支持。将它放在 CTE 中只会将那段不可读的代码移到其他地方。
          • 检查组合的表格方法有它的优点。使用表变量并将其连接到现有查询可以提供基于集合的解决方案而无需案例。这个答案是一个糟糕的例子,但表格的想法本身就有优点。
          【解决方案14】:
          SELECT 1 AS Saleable, *
            FROM @Product
           WHERE ( Obsolete = 'N' OR InStock = 'Y' )
          UNION
          SELECT 0 AS Saleable, *
            FROM @Product
           WHERE NOT ( Obsolete = 'N' OR InStock = 'Y' )
          

          【讨论】:

            【解决方案15】:
            SELECT CASE WHEN profile.nrefillno = 0 THEN 'N' ELSE 'R'END as newref
            From profile
            

            【讨论】:

              【解决方案16】:
              case statement some what similar to if in SQL server
              
              SELECT CASE 
                          WHEN Obsolete = 'N' or InStock = 'Y' 
                             THEN 1 
                             ELSE 0 
                     END as Saleable, * 
              FROM Product
              

              【讨论】:

              • 您能否解释一下这如何回答所提出的问题?
              • @Guanxi:虽然不是我的答案,但“案例”概括了“如果-则-否则”(从 2 个案例到多个案例)
              【解决方案17】:

              这不是答案,只是我工作时使用的 CASE 语句示例。它有一个嵌套的 CASE 语句。现在你知道为什么我的眼睛是交叉的。

               CASE orweb2.dbo.Inventory.RegulatingAgencyName
                  WHEN 'Region 1'
                      THEN orweb2.dbo.CountyStateAgContactInfo.ContactState
                  WHEN 'Region 2'
                      THEN orweb2.dbo.CountyStateAgContactInfo.ContactState
                  WHEN 'Region 3'
                      THEN orweb2.dbo.CountyStateAgContactInfo.ContactState
                  WHEN 'DEPT OF AGRICULTURE'
                      THEN orweb2.dbo.CountyStateAgContactInfo.ContactAg
                  ELSE (
                          CASE orweb2.dbo.CountyStateAgContactInfo.IsContract
                              WHEN 1
                                  THEN orweb2.dbo.CountyStateAgContactInfo.ContactCounty
                              ELSE orweb2.dbo.CountyStateAgContactInfo.ContactState
                              END
                          )
                  END AS [County Contact Name]
              

              【讨论】:

              • 重新格式化 Case 语句的编辑很好,也很花哨,使其更易于理解,但 SQL 仍然会在使用它的视图中出现。
              • 我只是想知道为什么CASE 被投票并标记为答案,而不是应该是答案的IF,就像这个一样,这仍然是CASEstatement,不是IF
              • @Mr.J:虽然不是我的答案,但“案例”概括了“如果-则-否则”(从 2 个案例到多个案例)
              【解决方案18】:

              如果您是第一次将结果插入到表中,而不是将结果从一个表传输到另一个表,这适用于 Oracle 11.2g:

              INSERT INTO customers (last_name, first_name, city)
                  SELECT 'Doe', 'John', 'Chicago' FROM dual
                  WHERE NOT EXISTS 
                      (SELECT '1' from customers 
                          where last_name = 'Doe' 
                          and first_name = 'John'
                          and city = 'Chicago');
              

              【讨论】:

              • 标签说 SQL Server, TSQL
              【解决方案19】:

              作为CASE 语句的替代解决方案,可以使用表驱动方法:

              DECLARE @Product TABLE (ID INT, Obsolete VARCHAR(10), InStock VARCHAR(10))
              INSERT INTO @Product VALUES
              (1,'N','Y'),
              (2,'A','B'),
              (3,'N','B'),
              (4,'A','Y')
              
              SELECT P.* , ISNULL(Stmt.Saleable,0) Saleable
              FROM
                  @Product P
                  LEFT JOIN
                      ( VALUES
                          ( 'N', 'Y', 1 )
                      ) Stmt (Obsolete, InStock, Saleable)
                      ON  P.InStock = Stmt.InStock OR P.Obsolete = Stmt.Obsolete
              

              结果:

              ID          Obsolete   InStock    Saleable
              ----------- ---------- ---------- -----------
              1           N          Y          1
              2           A          B          0
              3           N          B          1
              4           A          Y          1
              

              【讨论】:

              • Saleable 用于查询中的 where 条件?
              • 可以在where条件下使用。
              【解决方案20】:
              SELECT CASE WHEN Obsolete = 'N' or InStock = 'Y' THEN 1 ELSE 0 
                           END AS Saleable, * 
              FROM Product
              

              【讨论】:

                【解决方案21】:

                您可以有两种选择来实际实现:

                1. 使用从 SQL Server 2012 引入的 IIF:

                  SELECT IIF ( (Obsolete = 'N' OR InStock = 'Y'), 1, 0) AS Saleable, * FROM Product
                  
                2. 使用Select Case

                  SELECT CASE
                      WHEN Obsolete = 'N' or InStock = 'Y'
                          THEN 1
                          ELSE 0
                      END as Saleable, *
                      FROM Product
                  

                【讨论】:

                  【解决方案22】:

                  对于使用 SQL Server 2012 的用户,IIF 是一项已添加的功能,可替代 Case 语句。

                  SELECT IIF(Obsolete = 'N' OR InStock = 'Y', 1, 0) AS Salable, *
                  FROM   Product 
                  

                  【讨论】:

                  【解决方案23】:
                  SELECT
                  if((obsolete = 'N' OR instock = 'Y'), 1, 0) AS saleable, *
                  FROM
                  product;
                  

                  【讨论】:

                    【解决方案24】:
                      SELECT IIF(Obsolete = 'N' OR InStock = 'Y',1,0) AS Saleable, * FROM Product
                    

                    【讨论】:

                    • 嗨,苏吉特·辛格·比什特;您的代码可能是正确的,但在某些上下文中它会做出更好的答案;例如,您可以解释这个提议的更改如何以及为什么会解决提问者的问题,可能包括指向相关文档的链接。这将使它对他们更有用,对正在寻找类似问题的解决方案的其他网站读者也更有用。
                    • 这个答案没有添加任何新内容。事实上,这条完全相同的行已成为已接受答案for over 5 years 的一部分。
                    • 另外需要注意的是IIF仅适用于2012年开始的SQL Server
                    【解决方案25】:

                    问题:

                    SELECT IF(Obsolete = 'N' OR InStock = 'Y' ? 1 : 0) AS Saleable, * FROM Product
                    

                    ANSI:

                    Select 
                      case when p.Obsolete = 'N' 
                      or p.InStock = 'Y' then 1 else 0 end as Saleable, 
                      p.* 
                    FROM 
                      Product p;
                    

                    使用别名——在这种情况下为p——将有助于防止出现问题。

                    【讨论】:

                      【解决方案26】:

                      使用 SQL CASE 就像使用普通的 If / Else 语句一样。 在下面的查询中,如果过时值 = 'N' 或如果 InStock 值 = 'Y' 则输出将为 1。否则输出将为 0。 然后我们将 0 或 1 值放在可销售列下。

                      SELECT
                            CASE 
                              WHEN obsolete = 'N' OR InStock = 'Y' 
                              THEN 1 
                              ELSE 0 
                            END AS Salable
                            , * 
                      FROM PRODUCT
                      

                      【讨论】:

                      • 就像普通的 If / Else 语句。如果过时值 = 'N' 或如果 InStock 值 = 'Y' 则输出将为 1。否则输出将为 0。
                      • 谢谢。请Edit您的帖子添加此说明。 Like:SQL 中的If..Then...Else.. 语句用法如下......
                      【解决方案27】:

                      会是这样的:

                      SELECT OrderID, Quantity,
                      CASE
                          WHEN Quantity > 30 THEN "The quantity is greater than 30"
                          WHEN Quantity = 30 THEN "The quantity is 30"
                          ELSE "The quantity is under 30"
                      END AS QuantityText
                      FROM OrderDetails;
                      

                      【讨论】:

                      • 我们可以在查询的 where 条件中使用 QuantityText 值吗?例如SELECT OrderID, Quantity, CASE WHEN Quantity &gt; 30 THEN "The quantity is greater than 30" WHEN Quantity = 30 THEN "The quantity is 30" ELSE "The quantity is under 30" END AS QuantityText FROM OrderDetails WHERE QuantityText = 'The quantity is 30';
                      【解决方案28】:
                      SELECT 
                        CAST(
                          CASE WHEN Obsolete = 'N' 
                          or InStock = 'Y' THEN ELSE 0 END AS bit
                        ) as Saleable, * 
                      FROM 
                        Product
                      

                      【讨论】:

                      • 点评来源: 欢迎来到 Stack Overflow!请不要只用源代码回答。尝试对您的解决方案如何工作提供一个很好的描述。请参阅:How do I write a good answer?。谢谢
                      • 我想你会发现这不会执行,因为它缺少任何跟在 'THEN' 关键字后面的输出。
                      【解决方案29】:

                      为了完整起见,我要补充一点,SQL 使用三值逻辑。表达式:

                      obsolete = 'N' OR instock = 'Y'
                      

                      可能产生三种不同的结果:

                      | obsolete | instock | saleable |
                      |----------|---------|----------|
                      | Y        | Y       | true     |
                      | Y        | N       | false    |
                      | Y        | null    | null     |
                      | N        | Y       | true     |
                      | N        | N       | true     |
                      | N        | null    | true     |
                      | null     | Y       | true     |
                      | null     | N       | null     |
                      | null     | null    | null     |
                      

                      因此,例如,如果产品已过时但您不知道产品是否有库存,那么您不知道产品是否可销售。这个三值逻辑可以写成如下:

                      SELECT CASE
                                 WHEN obsolete = 'N' OR instock = 'Y' THEN 'true'
                                 WHEN NOT (obsolete = 'N' OR instock = 'Y') THEN 'false'
                                 ELSE NULL
                             END AS saleable
                      

                      一旦弄清楚它是如何工作的,就可以通过决定 null 的行为将三个结果转换为两个结果。例如。这会将 null 视为不可销售:

                      SELECT CASE
                                 WHEN obsolete = 'N' OR instock = 'Y' THEN 'true'
                                 ELSE 'false' -- either false or null
                             END AS saleable
                      

                      【讨论】:

                        【解决方案30】:

                        我喜欢使用 CASE 语句,但问题要求在 SQL Select 中使用 IF 语句。我过去使用的是:

                        SELECT
                        
                           if(GENDER = "M","Male","Female") as Gender
                        
                        FROM ...
                        

                        这就像 excel 或 sheet IF 语句,其中有一个条件,然后是真条件,然后是假条件:

                        if(condition, true, false)
                        

                        此外,您可以嵌套 if 语句(但使用时应该使用 CASE :-)

                        (注意:这适用于 MySQLWorkbench,但可能不适用于其他平台)

                        【讨论】:

                        • IF FUNCTION 似乎在 MySQL 中存在,但在 MSSQL 中不存在,在 MSSQL 中 IIF 从 2012 版本开始可以使用。
                        猜你喜欢
                        • 2021-07-25
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2011-08-20
                        • 1970-01-01
                        • 1970-01-01
                        • 2014-07-03
                        • 2018-09-19
                        相关资源
                        最近更新 更多