如何在SQL SELECT中执行IF…THEN?


1508

如何IF...THENSQL SELECT陈述中执行?

例如:

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

14
您可能需要看一下此链接。关于:SQL WHERE子句:避免使用CASE,请使用布尔逻辑
某人2012年

3
@Somebody:不太相关,因为本文讨论了使用逻辑重写规则将蕴涵转换为析取关系。线索是“逻辑”一词,即可以解析为真或假的东西,不适用于投影。TL; DR条款适用于WHERECHECK但不适用于SELECT
2016年

6
@MartinSmith的答案是最优雅的-在SQL 2012+中使用IIF。
Murray Foxcroft

Answers:


1760

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语句,该语句也可以在访问使用(由Martin Smith指出):

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

57
请注意,在使用手提箱时,请不要将您的情况限制在刹车片中。花了很多时间才意识到:)
Archan Mishra 2011年

17
别忘了结束
Simon_Weaver 2014年

8
和AS位!
卡布隆

8
Case,When,Else和End应该平行(沿着同一行)缩进-然后才应该向内缩进-最适合我。
Ujjwal Singh 2014年

6
@ReeveStrife仅适用于iif SQL Server 2012+
stuartdotnet

327

在这种情况下,案例陈述是您的朋友,采用两种形式之一:

简单的情况:

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子句中,以进行真正的排序。


32
我知道这很老了,但我想应该指出的是,您可以在AS Col_Name后面加上a END来命名结果列
Ben

9
我总是觉得第二个比较简单。
霍根

4
同意,我几乎总是使用扩展的case语句,因为要测试的条件总是比一个变量本身更复杂。对我来说,阅读起来也更容易。
magnum_pi '16

1
很好地解释了两种情况,有无变量都没有。使用变量,条件需要满足case语句后的变量与条件所基于的条件之间的相等性,没有变量,则可以添加自足条件进行测试。
Remus.18年

第二种选择让我更加方便。两者同样好。
斯坦利·奥克拉帕·努沃萨

277

在SQL Server 2012中,您可以使用此IIF功能

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

实际上,这只是一种简写(尽管不是标准的SQL)写法CASE

与扩展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

但是,有时必须小心避免这种方法引起的参数嗅探问题


6
如果要使用SQL中的IF..then语句,这应该是答案。
J.先生

91

您可以在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

4
请参阅:meta.stackexchange.com/questions/103053/…进行有趣的讨论。如果您提供的两个链接确实增加了我支持的额外上下文。
山姆·萨弗隆

2
引用真的很有用,如果有其他详细信息,强烈建议您参考
baymax

75

使用案例。这样的东西。

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

50
SELECT  
(CASE 
     WHEN (Obsolete = 'N' OR InStock = 'Y') THEN 'YES'
                                            ELSE 'NO' 
 END) as Salable
, * 
FROM Product

48

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

1
您为什么不干脆将where Obsolete = 'N' or InStock = 'Y'其切成两半
maksymiuk

46

通过此链接,我们可以IF THEN ELSE在T-SQL中理解:

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来说这还不够吗?


3
这不是请求者想要的,但是对于知道可以 select语句之外使用if语句非常有用。
乔纳森

2
EXISTS很好,因为如果找到了项目,它将退出搜索循环。COUNT一直运行到表行末尾。与问题无关,但要知道一些事情。
JustJohn


32

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

2
晚了,但是可以SELECT按照OP的要求在内部使用吗?
阿卜杜勒·卡尤姆


24

使用CASE语句:

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

etc...

23

使用纯位逻辑:

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

请参阅工作演示:如果没有case,则在SQL Server中

首先,您需要计算truefalse选定条件的值。这是两个NULLIF

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

组合在一起得出1或0。接下来使用按位运算符

这是最所见即所得的方法。


19
-1用于代码混淆。严重的是,这与所见即所得的距离差不多!一片红润的无法理解的烂摊子,如果我必须处理您的代码,我会整天咒骂……对不起:-/
Heliac

2
@Heliac将cte放在View中,您将永远看不到混乱。对于漫长而复杂的AND(或)运算符,它不比CASE(当然是cte之外的部分)更具可读性。
Tomasito 2013年

1
我将它的整洁度设为+1,但请注意,当前问题的答案是错误的。您需要一个“ |” 不是“&”。
Mark Hurd

3
完全同意@Heliac。虽然它在语法上是正确的并且可以正常工作,但它并不容易得到支持。将其放在CTE中只会将这段不可读的代码移到其他地方。
objectNotFound

1
表格检查组合可能有其优点。使用表变量并将其连接到现有查询可以提供无条件的基于集合的解决方案。这个答案是一个很差的例子,但是餐桌创意本身是值得的。
Suncat2000

19
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' )


14
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

2
您能对此问题的回答方式做些解释吗?
关西2015年

@Guanxi:尽管不是我的回答,但“案例”概括了“ if-then-else”(从2个案例到很多案例)
JosephDoggie

你能详细说明吗?
Peter Mortensen

13

这不是答案,只是我在工作中使用的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]

1
重新格式化Case语句的编辑既好又花哨,使它更易于理解,但是SQL仍会在使用它的视图中将其汇总。
JustJohn

1
我只是在徘徊为什么会CASE被投票并标记为答案,而不是IF应该作为答案的答案,就像这样,这仍然是一个CASE陈述,而不是一个IF
J.先生

@ Jr.J:虽然不是我的回答,但“案例”概括了“ if-then-else”(从2个案例到很多案例)
JosephDoggie

12

如果您是第一次将结果插入表中,而不是将结果从一个表转移到另一个表,那么这在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');

4
标签说SQL Server,TSQL
Malachi

11

作为该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

可售用于查询中的条件?
Bhavin Thummar

可以在有条件的地方使用。
Serkan Arslan

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


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

7
嗨Surjeet Singh Bisht;您的代码可能是正确的,但在某些情况下,它将提供更好的答案;例如,您可以解释此提议的更改如何以及为什么能够解决发问者的问题,也许包括相关文档的链接。这将使其对他们更有用,对正在寻找类似问题的解决方案的其他站点读者也将更有用。
文斯·鲍德伦

5
此答案不会添加任何新内容。实际上,已经超过5年的时间,这条相同的线已成为公认答案的一部分。
SL Barth-恢复莫妮卡

1
此外,重要的是要提到IIF仅适用于从2012
Ivan Rascon

5

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

  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

4

题:

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在这种情况下,使用别名将有助于防止出现问题。


3

使用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

1
听起来不错。也许一两个词来解释它?
JQSOFT

就像普通的If / Else语句一样。如果过时的值=“N”或如果INSTOCK值=“Y”然后输出将是1,否则输出将为0
Tharuka

1
谢谢。请编辑您的帖子以添加此说明。这样的:该If..Then...Else..语句使用情况SQL如下....
JQSOFT

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

8
点评来源:欢迎来到Stack Overflow!请不要只回答源代码。尝试提供有关您的解决方案如何工作的很好的描述。请参阅:我如何写一个好的答案?。谢谢
sɐunıɔןɐqɐp

3
我想您会发现它没有执行,因为它缺少'THEN'关键字之后的任何输出。
Dodecaphone

你能详细说明吗?
Peter Mortensen

2

将会是这样的:

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 > 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';
Bhavin Thummar,

1

为了完整起见,我要补充一点,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

0

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

SELECT

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

FROM ...

就像excel或工作表IF语句一样,先有条件,然后是真条件,然后是假条件:

if(condition, true, false)

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

(注意:这在MySQLWorkbench中有效,但在其他平台上可能无效)


0

您可以使用案例声明:

Select 
Case WHEN (Obsolete = 'N' or InStock = 'Y') THEN 1 ELSE 0 END Saleable,
Product.*
from Product
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.