如何执行 IF...那么在 SQL SELECT 中?

How do I perform an IF...THEN in an SQL SELECT?

提问人:Eric Labashosky 提问时间:9/15/2008 最后编辑:DineshDBEric Labashosky 更新时间:11/1/2023 访问量:4536295

问:

如何在语句中执行?IF...THENSQL SELECT

例如:

SELECT IF(Obsolete = 'N' OR InStock = 'Y' ? 1 : 0) AS Saleable, * FROM Product
sql-server t-sql if-statement 案例

评论


答:

62赞 John Sheehan 9/15/2008 #1
SELECT  
(CASE 
     WHEN (Obsolete = 'N' OR InStock = 'Y') THEN 'YES'
                                            ELSE 'NO' 
 END) as Salable
, * 
FROM Product
87赞 palehorse 9/15/2008 #2

用例。像这样的东西。

SELECT Salable =
        CASE Obsolete
        WHEN 'N' THEN 1
        ELSE 0
    END
50赞 Santiago Cepas 9/15/2008 #3
 SELECT
   CASE 
      WHEN OBSOLETE = 'N' or InStock = 'Y' THEN 'TRUE' 
      ELSE 'FALSE' 
   END AS Salable,
   * 
FROM PRODUCT
2031赞 Darrel Miller 9/15/2008 #4

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

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

仅当希望将结果作为布尔值时,才需要使用运算符。如果您对 感到满意,则有效:CASTint

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

评论

5赞 1/27/2017
谨防 CASE/IIF 的肮脏秘密:sqlperformance.com/2014/06/t-sql-queries/......
0赞 ftani 9/14/2022
我按照本教程在 SQLite3 数据库上实现了这一点: sqlitetutorial.net/sqlite-functions/sqlite-iif
114赞 sven 9/15/2008 #5

你可以在 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
51赞 user7658 9/15/2008 #6

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赞 maraaaaaaaa 6/8/2019
你为什么不干脆把地方切成两半where Obsolete = 'N' or InStock = 'Y'
25赞 Christopher 9/15/2008 #7

使用 CASE 语句:

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

etc...
365赞 Jonathan 9/15/2008 #8

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

简单的案例:

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>

您甚至可以将案例陈述按子句顺序排列,以便进行非常花哨的排序。

52赞 Ken 1/6/2010 #9

通过此链接,我们可以在 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 来说,这还不够好吗?

评论

3赞 Jonathan 4/10/2013
这不是请求者想要的,但对于知道您可以在 select 语句之外使用 if 语句非常有用。
2赞 JustJohn 2/12/2016
EXISTS 很好,因为如果找到项目,它会踢出搜索循环。COUNT 将一直运行到表行末尾。与问题无关,但要知道一些事情。
318赞 Martin Smith 7/21/2011 #10

在 SQL Server 2012 中,可以使用 IIF 函数来实现此目的。

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

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

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

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

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

但是,有时必须注意避免使用这种方法的参数嗅探问题

10赞 Robert B. Grossman 10/26/2012 #11

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

评论

6赞 Malachi 12/27/2012
标签显示 SQL Server、TSQL
23赞 Tomasito 6/9/2013 #12

使用纯位逻辑:

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

请参阅工作演示:if then without case in SQL Server

首先,您需要计算出所选条件的值和值。这里有两个 NULLIFtruefalse

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

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

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

评论

19赞 Riegardt Steyn 6/22/2013
-1 表示代码混淆。说真的,这与所见即所得的距离差不多!一团红润的不可读的烂摊子,如果我不得不处理你的代码,我会整天咒骂......不好意思:-/
2赞 Tomasito 6/23/2013
@Heliac将 cte 部分放入 View 中,您将永远不会看到混乱。对于冗长而复杂的 AND、OR、NOT 它比 CASE(当然是 cte 之外的那部分)更具可读性。
1赞 Mark Hurd 11/16/2016
一旦它进入 cte,我就给它打了 +1 的整洁度,但请注意,这个问题的答案目前是错误的。您需要一个“|”而不是“&”。
3赞 objectNotFound 11/25/2017
完全同意@Heliac。虽然它在语法上是正确的并且工作正常,但它并不容易支持。把它放在 CTE 中只会将那段不可读的代码移动到其他地方。
1赞 Suncat2000 11/30/2018
检查组合的表格方法可能有其优点。使用表变量并将其联接到现有查询可以提供基于集合的解决方案,而无需案例。这个答案是一个糟糕的例子,但表格的想法本身是有道理的。
4赞 Dibin 1/8/2014 #13

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

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

评论

2赞 jk7 11/1/2018
这个答案重复了马丁·史密斯几年前在答案中已经提供的内容(细节较少)。
16赞 Mohammad Atiour Islam 8/25/2015 #14
SELECT CASE WHEN profile.nrefillno = 0 THEN 'N' ELSE 'R'END as newref
From profile
13赞 Chanukya 12/9/2015 #15
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

评论

3赞 Guanxi 12/9/2015
您能否解释一下这如何回答所提出的问题?
0赞 JosephDoggie 10/3/2018
@Guanxi:虽然不是我的答案,但“案例”概括了“如果,那么其他”(从2个案例到多个案例)
34赞 Ravi Anand 12/18/2015 #16

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

DECLARE @val INT;
SET @val = 15;

IF @val < 25
PRINT 'Hi Ravi Anand';
ELSE
PRINT 'By Ravi Anand.';

GO

嵌套 if...SQL Server 中的 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

评论

3赞 abdul qayyum 2/17/2019
迟到了,但它可以像 OP 问的那样在里面使用吗?SELECT
13赞 JustJohn 2/12/2016 #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]

评论

1赞 JustJohn 10/13/2016
重新格式化 Case 语句的编辑很好,花花公子,使其更易于理解,但 SQL 仍然会全部集中在使用它的视图中。
1赞 Mr.J 3/22/2017
我只是在徘徊,为什么被点赞并标记为答案,而不是应该是答案,就像这个一样,这仍然是一个陈述,而不是一个.CASEIFCASEIF
0赞 JosephDoggie 10/3/2018
@Mr.J:虽然不是我的答案,但“案例”概括了“if-then-else”(从2个案例到多个案例)
24赞 sandeep rawat 4/26/2016 #18

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

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

评论

2赞 jk7 11/1/2018
这个答案重复了马丁·史密斯几年前在答案中已经提供的内容(细节较少)。
1赞 sandeep rawat 11/1/2018
@jk7这是这个问题的第一个答案。
5赞 jk7 11/2/2018
不是从我所看到的。它说您的答案发布于 Apr 26 '16,Martin's 发布于 Jul 20 '11。
18赞 onedaywhen 5/11/2016 #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' )
9赞 user8422856 8/9/2017 #20
SELECT CASE WHEN Obsolete = 'N' or InStock = 'Y' THEN 1 ELSE 0 
             END AS Saleable, * 
FROM Product
10赞 Serkan Arslan 1/31/2018 #21

作为该语句的替代解决方案,可以使用表驱动的方法: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

评论

0赞 Bhavin Thummar 11/8/2019
Saleable 用于查询中的 where 条件?
0赞 Serkan Arslan 11/8/2019
它可以在什么条件下使用。
5赞 David Cohn 11/2/2018 #22

问题:

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

评论

0赞 Peter Mortensen 9/23/2022
“ANSI”是什么意思?ANSI SQL?什么版本?1992?2011?例如,与什么相反?它测试了什么?请通过编辑(更改)您的答案来回复,而不是在评论中(************“编辑:”,“更新:”或类似内容 - 答案应该看起来像今天写的一样)。
8赞 user11127093 3/1/2019 #23

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

  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
    
3赞 Muhammad Awais 10/31/2019 #24

它将是这样的:

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;

评论

1赞 Bhavin Thummar 11/8/2019
我们可以在查询的 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';
2赞 Salman A 11/28/2019 #25

为了完整起见,我想补充一点,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
8赞 Tharuka Madumal 2/18/2020 #26

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

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

评论

1赞 Tharuka Madumal 2/18/2020
这就像普通的 If / Else 语句一样。如果过时的值 = 'N' 或 如果 InStock 值 = 'Y',则输出将为 1。否则输出将为 0。
2赞 2/18/2020
谢谢。请编辑您的帖子以添加此解释。比如:语句用法如下。If..Then...Else..SQL
0赞 Peter Mortensen 9/18/2022
“可销售”?不是“可销售”吗?
4赞 Prashant Marathay 4/9/2020 #27

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

SELECT

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

FROM ...

这就像 Excel 或工作表 IF 语句一样,其中有一个条件,然后是真条件,然后是假条件:

if(condition, true, false)

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

(注意:这在 MySQL Workbench 中有效,但在其他平台上可能不起作用)

评论

2赞 Luuk 8/1/2020
IF 函数它似乎存在于MySQL中,但不存在于MSSQL中,在MSSQL中,IIF可以从2012版本开始使用。
5赞 yusuf hayırsever 11/25/2020 #28
SELECT
if((obsolete = 'N' OR instock = 'Y'), 1, 0) AS saleable, *
FROM
product;
1赞 durlove roy 4/20/2022 #29

有多种条件。

SELECT

(CASE
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1001' THEN 'DM'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1002' THEN 'GS'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1003' THEN 'MB'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1004' THEN 'MP'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1005' THEN 'PL'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1008' THEN 'DM-27'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1011' THEN 'PB'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1012' THEN 'UT-2'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1013' THEN 'JGC'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1014' THEN 'SB'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1015' THEN 'IR'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1016' THEN 'UT-3'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1017' THEN 'UT-4'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1019' THEN 'KR'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1020' THEN 'SYB-SB'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1021' THEN 'GR'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1022' THEN 'SYB-KP'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1026' THEN 'BNS'

  ELSE ''
END) AS OUTLET

FROM matrixcrm.Transact

评论

0赞 Peter Mortensen 9/18/2022
为什么是18?为什么不是 19 岁?所有的幻数和字母代码是什么意思?例如,什么是“海上青焙坊-KP”?为什么要进行所有冗余?解释是有序的。例如,想法/要点是什么?从帮助中心:“......始终解释为什么您提出的解决方案是合适的,以及它是如何工作的”。请通过编辑(更改)您的答案来回复,而不是在评论中(**********************“编辑:”,“更新:”或类似内容 - 答案应该看起来像今天写的一样)。
0赞 tunnelview 11/1/2023 #30

看起来像一个老问题,但是如果我理解了您的问题并且正确思考,您想在 SQL 中实现 if/else 条件语句。两者都作为单独的列进行计算。

该函数于 2012 年引入,但让我们了解 and 语句之间的区别。如果你只需要写一个条件,那么就足够了,但是如果你想在一个语句中写多个条件,那么你将不得不使用“case”语句,如上面的响应所示。下面是一个示例供您参考。iif()caseiif()iif()iif()

   `select 
    s.name,s.mrn, 
    s.specialtyshort,
    s.admissiondate, 
    s.dischargedate,
    iif(s.admissiondate is not null, 'linked','notlinked') as s.admissionStatus 
    from specialty s`

现在,如果您需要在上述语句中包含任何其他过滤器或条件,则需要编写另一条语句。另一方面,表达式可以在一个表达式中包含多个条件。对语句和表达式之间的区别进行一些研究。下面是一个计算结果为值的表达式。iif()casecasecasecase

`select
 t.name 
,t.MRID
,t.operationDate
,t.dischargeDate
,case 
     when t.specialty like '%obstetrics%' then 'OBS'
     when t.specialty like '%orthopaedics%' then 'ORT'
     when t.specialty like '%General Surgery%' then 'GEN'
     when t.specialty like '%Cardiology%' then 'CAR'
else 'not available' --evaluates to a value.
end as derived_specialty

from 
OperationsTables t`