翻译Stairway to T-SQL: Beyond The Basics Level 6: Using the CASE Expression and IIF Function

原文链接:http://www.sqlservercentral.com/articles/Stairway+Series/108723/

T-SQL的楼梯:超越基本级别6:使用案例表达式和IIF函数

该系列

本文是阶梯系列的一部分:t-sql的阶梯:超越极限

从他的楼梯到t-sql DMLGregory Larsen涵盖了更高级的t-sql语言,比如子查询。

有时,您需要编写一个TSQL语句,该语句能够根据对另一个表达式的评估返回不同的TSQL表达式。当您需要这种功能时,您可以使用CASE表达式或IIF函数来满足此需求。在本文中,我将回顾该案例和IIF语法,并向您展示案例表达式和IIF函数的示例。

理解case表达

transact-sql CASE表达式允许您将条件逻辑放入您的TSQL代码中。这个条件逻辑为您提供了在TSQL语句中放置不同的代码块的方法,这些代码块可以根据条件逻辑的真实或错误的评估来执行。您可以在一个CASE表达式中放置多个条件表达式。当您的CASE子句中有多个条件表达式时,第一个计算为TRUE的表达式将是由您的TSQL语句计算的代码块。为了更好地理解案例表达式是如何工作的,我将回顾案例表达式的语法,然后通过一系列不同的示例。

Case表达式语法

CASE表达式有两种不同的格式:简单和搜索。这两种类型的格式稍有不同,如1所示。

 

Simple CASE expression:

 

CASE input_expression

     WHEN when_expression THEN result_expression [ ...n ]

     [ ELSE else_result_expression ]

END

Searched CASE expression:

 

CASE

     WHEN Boolean_expression THEN result_expression [ ...n ]

     [ ELSE else_result_expression ]

END

1:案例表达式语法

 

通过查看图1中的CASE表达式的两种不同格式,您可以看到每种格式如何提供一种不同的方式来标识一个确定案例表达式结果的多个表达式。对于这两种情况,每个子句都执行一个布尔测试。在简单的CASE表达式中,布尔测试的左手边出现在CASE单词之后,被称为“input表达式,而布尔测试的右边则是在单词后面,被称为表达式的时候。对于简单的CASE表达式,“input表达式表达式之间的运算符始终是相等的运算符。而对于搜索的CASE表达式,每个子句将包含一个布尔表达式。这个布尔表达式可以是一个简单的布尔表达式,它可以是一个运算符,也可以是一个具有许多不同条件的复杂布尔表达式。此外,搜索的CASE表达式可以使用全部的布尔运算符。

不管使用哪种CASE格式,每个子句都按照它出现的顺序进行比较。CASE表达式的结果将基于第一个计算为TRUE的子句。如果no当子句的值为TRUE时,则返回ELSE表达式。当ELSE子句被省略,当子句的值为TRUE时,然后返回NULL值。

样本数据的例子

为了使用案例表达式演示一个表,我将使用清单1中的脚本创建一个名为MyOrder的示例表。如果您愿意跟随我的示例,并在SQL Server实例上运行它们,那么可以在您选择的数据库中创建这个表。

 

CREATE TABLE MyOrder (

ID int identity,

OrderDT date,

OrderAmt decimal(10,2),

Layaway char(1));

INSERT into MyOrder VALUES

('12-11-2012', 10.59,NULL),

('10-11-2012', 200.45,'Y'),

('02-17-2014', 8.65,NULL),

('01-01-2014', 75.38,NULL),

('07-10-2013', 123.54,NULL),

('08-23-2009', 99.99,NULL),

('10-08-2013', 350.17,'N'),

('04-05-2010', 180.76,NULL),

('03-27-2011', 1.49, NULL);

清单1:创建示例表MyOrder

 

使用一个简单的案例表达式来表示何时和其他表达式

为了演示简单的CASE表达式格式如何工作,让我运行清单2中的代码。

 

SELECT YEAR(OrderDT) AS OrderYear,

       CASE YEAR(OrderDT)

 WHEN 2014 THEN 'Year 1'

 WHEN 2013 THEN 'Year 2'

 WHEN 2012 THEN 'Year 3'

 ELSE 'Year 4 and beyond' END AS YearType

FROM MyOrder;

清单2:使用ELSE表达式的简单的CASE表达式

让我先来解释一下为什么这是一个简单的例子。如果您查看清单2中的代码,您可以看到,在单词CASE之后,我指定了表达式年份(OrderDT)”,然后我按照三个不同的表达式,分别从2014年开始使用不同的年份。因为我在CASE和第一个关键字之间指定了这个表达式,它告诉SQL Server这是一个简单的CASE表达式。

 

当我的简单的CASE表达式被求值时,它使用相等运算符(“=”)(OrderDate)”值和不同的表达式之间。因此,清单1中的代码将显示为YearType“1OrderDT年值“2014”,或将显示“2OrderDT一年的将显示“2013”或者三年级OrderDT年的“2012”。如果OrderDT的年份不匹配任何表达式,那么ELSE条件将显示4年和以后

 

当我运行清单2中的代码时,我得到了结果1中所示的输出。

 

OrderYear   YearType

----------- -----------------

2012        Year 3

2012        Year 3

2014        Year 1

2014        Year 1

2013        Year 2

2009        Year 4 and beyond

2013        Year 2

2010        Year 4 and beyond

2011        Year 4 and beyond

结果1:运行清单2时的结果

 

使用一个没有ELSE表达式的简单的CASE表达式

让我运行清单3中的代码,它将展示当一个简单的CASE表达式没有其他子句时发生了什么。

 

SELECT YEAR(OrderDT) AS OrderYear,

       CASE YEAR(OrderDT)

 WHEN 2014 THEN 'Year 1'

 WHEN 2013 THEN 'Year 2'

 WHEN 2012 THEN 'Year 3' END AS YearType

FROM MyOrder;

清单3:没有ELSE语句的简单情况表达式

 

清单3中的代码与清单2中的代码类似,但没有ELSE子句。当我运行清单3中的代码时,它会生成结果2中所示的结果。

 

OrderYear   YearType

----------- --------

2012        Year 3

2012        Year 3

2014        Year 1

2014        Year 1

2013        Year 2

2009        NULL

2013        Year 2

2010        NULL

2011        NULL

结果2:运行清单3时的结果

 

通过查看结果2中的输出,您可以看到,在MyOrder表中的OrderDT年没有满足任何的when子句条件时,SQL Server将显示该行的一年类型值的“NULL”

使用搜索的案例表达式

在简单的情况表达式中,根据相等运算符对表达式求值。使用搜索的CASE表达式,您可以使用其他操作符,而CASE表达式语法略有不同。为了演示这一点,让我们看一下清单4中的代码。

 

SELECT YEAR(OrderDT) AS OrderYear,

       CASE

 WHEN YEAR(OrderDT) = 2014 THEN 'Year 1'

 WHEN YEAR(OrderDT) = 2013 THEN 'Year 2'

 WHEN YEAR(OrderDT) = 2012 THEN 'Year 3'

 WHEN YEAR(OrderDT) < 2012 THEN 'Year 4 and beyond'

                       END AS YearType

FROM MyOrder;

 

清单4:搜索的案例表达式

 

如果查看清单4中的代码,可以看到WHEN子句在CASE子句后面直接跟随,而在这两个子句之间没有文本。这告诉SQL Server这是一个搜索的案例表达式。还要注意每个子句后面的布尔表达式。正如您所看到的,不是所有的布尔表达式都在使用相等运算符,最后一个表达式使用的是小于(“小于”)运算符。清单4中的案例表达式与清单2中的CASE表达式的逻辑是一样的。因此,当我运行清单4中的代码时,它产生的结果与结果1中所示的结果相同。

如果表达式值为TRUE时,会返回什么表达式?

当表达式在单个情况表达式中求值时,可能会出现不同的情况。当这种情况发生时,SQL Server将返回与第一个表达式相关联的结果表达式,该表达式求值为true。因此,当多个子句被计算为真时,您的子句的顺序将控制从您的CASE表达式返回的结果。

 

展示我们用这样的表情来显示“200美元的秩序”OrderAmt 200美元的范围内时,“100美元的秩序”OrderAmt100美元的范围内和“< 100美元订单OrderAmt小于100美元当一个OrderAmt不属于任何这些类别的分类顺序为“300美元以上的秩序。让我们回顾一下清单5中的代码,以演示当尝试将订单分类为一个orderamtcategory值时,当多个表达式值为TRUE时,会发生什么情况。

SELECT OrderAmt,

       CASE

 WHEN OrderAmt < 300 THEN '200 Dollar Order'

 WHEN OrderAmt < 200 THEN '100 Dollar Order'

 WHEN OrderAmt < 100 THEN '< 100 Dollar Order'

 ELSE  '300 Dollar and above Order'

     END AS OrderAmt_Category

FROM MyOrder;

清单5:当表达式值为TRUE时,多个表达式的值

 

当我运行清单5中的代码时,我得到了结果3中的输出。

 

OrderAmt                                OrderAmt_Category

--------------------------------------- --------------------------

10.59                                   200 Dollar Order

200.45                                  200 Dollar Order

8.65                                    200 Dollar Order

75.38                                   200 Dollar Order

123.54                                  200 Dollar Order

99.99                                   200 Dollar Order

350.17                                  300 Dollar and above Order

180.76                                  200 Dollar Order

1.49                                    200 Dollar Order

结果3:运行清单5时的结果

 

通过查看结果3中的结果,您可以看到每个订单都是200300或以上的订单,我们知道这是不正确的。之所以发生这种情况,是因为我只使用小于(“小于”)操作符来简单地对订单进行简单的分类,从而在表达式中对表达式求值时,会导致多个表达式。WHEN子句的排序不允许返回正确的表达式。

 

通过重新订购我的条款,我可以得到我想要的结果。清单6中的代码与清单5相同,但我重新排序了WHEN子句,以便正确地对我的订单进行分类。

 

SELECT OrderAmt,

       CASE

 WHEN OrderAmt < 100 THEN '< 100 Dollar Order'

 WHEN OrderAmt < 200 THEN '100 Dollar Order'

 WHEN OrderAmt < 300 THEN '200 Dollar Order'

 ELSE  '300 Dollar and above Order'

     END AS OrderAmt_Category

FROM MyOrder;

清单6:与清单5相似的代码,但是当子句处于不同的顺序时

 

当我运行清单5中的代码时,我得到了结果4中的输出。

OrderAmt                                OrderAmt_Category

--------------------------------------- --------------------------

10.59                                   < 100 Dollar Order

200.45                                  200 Dollar Order

8.65                                    < 100 Dollar Order

75.38                                   < 100 Dollar Order

123.54                                  100 Dollar Order

99.99                                   < 100 Dollar Order

350.17                                  300 Dollar and above Order

180.76                                  100 Dollar Order

1.49                                    < 100 Dollar Order

结果4:运行清单6时的结果

 

通过查看结果4中的输出,您可以看到,通过更改表达式的顺序,我得到了每个订单的正确结果。

嵌套case表达式

偶尔,您可能需要进行额外的测试,以使用CASE表达式进一步对数据进行分类。当出现这种情况时,您可以使用一个嵌套的CASE表达式。清单7中的代码展示了一个示例,用于在MyOrder表中进一步对订单进行分类,以确定订单是否在订单超过200美元时使用外拉值购买。

SELECT OrderAmt,

       CASE

 WHEN OrderAmt < 100 THEN '< 100 Dollar Order'

 WHEN OrderAmt < 200 THEN '100 Dollar Order'

 WHEN OrderAmt < 300 THEN

CASE

WHEN Layaway = 'N'

   THEN '200 Dollar Order without Layaway'

   ELSE '200 Dollar Order with Layaway' END

 ELSE  

CASE

WHEN Layaway = 'N'

   THEN '300 Dollar Order without Layaway'

   ELSE '300 Dollar Order with Layaway' END

     END AS OrderAmt_Category

FROM MyOrder;

清单7:嵌套案例语句

 

清单7中的代码与清单6中的代码类似。唯一不同的是,我添加了一个额外的CASE表达式,以查看MyOrder表中的订单是否使用lay客场选项购买,该选项仅允许购买超过200美元。记住,当您嵌套CASE表达式时,SQL Server只允许您有多达10个级别的嵌套。

可以使用case表达式的其他地方

到目前为止,我的所有示例都使用案例表达式来创建一个结果字符串,方法是将CASE表达式放在TSQL select语句的select列表中。您还可以在UPDATEDELETESET语句中使用CASE表达式。另外,案例表达式可以与in一起使用,ORDER BY HAVING 法则.在清单8中,我使用了一个表示WHERE子句的案例。

 

SELECT *

FROM MyOrder

WHERE CASE YEAR(OrderDT)

WHEN 2014 THEN 'Year 1'

WHEN 2013 THEN 'Year 2'

WHEN 2012 THEN 'Year 3'

ELSE 'Year 4 and beyond' END = 'Year 1';

清单8:WHERE子句中使用案例表达式

 

在清单8中,我只想在第一年中返回MyOrder表的一个订单。为了完成这一点,我将与清单2中在WHERE子句中使用的相同的CASE表达式进行了相同的处理。我将CASE表达式作为WHERE条件的左边部分,这样它就可以根据OrderDT列生成不同的年份字符串。然后,我测试了从CASE表达式生成的字符串,看它是否等于第一年的值,当它是一个行将从MyOrder表返回时。我将不推荐使用一个case表达式去选择一个时间从时间列像“Year 1”一样,还有其他更好的方法,比如使用年份函数来选择给定年份的行。我只是在这里演示了如何在WHERE子句中使用CASE语句。

使用IIF函数缩短案例表达式

随着SQL Server 2012的引入,微软加入了IIF功能。IIF函数可以被认为是CASE语句的快捷方式。在图2中,您可以找到IIF函数的语法。

 

IIF ( boolean_expression, true_value, false_value )

图像2IIF函数的语法

 

布尔表达式是一个有效的布尔表达式,它等于TRUEFALSE。当布尔表达式等于一个真值时,就会执行“truevalue”表达式。如果布尔表达式等同于FALSE,则执行伪值。就像案例表达式一样,IIF函数可以被嵌套到10个级别。

使用IIF的例子

为了演示如何使用IIF函数来替换CASE表达式,让我们来回顾一下清单9中使用搜索案例表达式的代码。

 

SELECT OrderAmt,

       CASE

 WHEN OrderAmt > 200 THEN 'High $ Order'

 ELSE 'Low $ Order' END AS OrderType

FROM MyOrder;

清单9:简单的例子表达的例子

 

清单9中的代码只有一个单独的表达式,用于确定OrderAmt是高还是低的订单。如果“OrderAMT-200”的表达式值为TRUE,那么OrderType值将被设置为“$$Order”。如果当表达式求值为FALSE时,则为OrderType值设置$Order”

 

使用IIF函数而不是CASE表达式的重写代码可以在清单10中找到。

 

SELECT OrderAmt,  

 IIF(OrderAmt > 200,

'High $ Order',

'Low $ Order') AS OrderType

FROM MyOrder;

清单10:使用IIF函数的示例

 

通过查看清单10,您可以看到为什么IIF函数被认为是CASE表达式的一个简化版本。用“IIF”(字符串,然后的子句替换为逗号,“ELSE”子句用逗号替换,“END”替换为“)”。当布尔表达式“OrderAmt-200”TRUE时,显示的值是$Order”。当布尔表达式“OrderAmt-200”被求值为FALSE时,将显示$Order”。如果您运行清单910中的代码,您将看到它们都产生相同的输出。

IIF函数的嵌套示例

就像CASE表达式SQL Server允许您嵌套IIF函数一样。清单11IIF函数嵌套的一个示例。

 

SELECT OrderAmt,

       IIF (OrderAmt < 100,

       '< 100 Dollar Order',

       (IIF (OrderAmt < 200,

        '100 Dollar Order',

             (IIF (OrderAmt < 300,

                    (IIF (Layaway = 'N',

           '200 Dollar Order without Layaway',

           '200 Dollar Order with Layaway'

           )

      ),

      (IIF (Layaway = 'N',

            '300 Dollar Order without Layaway',

            '300 Dollar Order with Layaway'

           )

                )

     )

)

         )

)

) AS OrderAmt_Category

FROM MyOrder;

清单11:IIF函数的嵌套示例

 

在本例中,您可以看到我已经多次使用IIF函数。每一个额外的一个都可以用在真值或者IIF函数的假值中。清单11中的代码等价于使用清单7中嵌套的CASE表达式的代码。

局限性

与大多数TSQL功能一样,存在一些限制。下面是关于这个案例和IIF构造的一些限制。

案例表达的局限性:

CASE表达式中,只能有10个层次的嵌套。

不能使用CASE表达式来控制TSQL语句的执行流。

IIF功能限制:

您只能有多达10个层次的IIF子句的嵌套。

摘要

CASE表达式和IIF函数允许您在TSQL代码中放置表达式逻辑,它将根据表达式的计算结果更改代码的结果。通过使用IIF函数和CASE表达式所支持的比较表达式,您可以根据比较表达式的值为TRUEFALSE来执行不同的代码块。案例表达式和IIF函数为您提供了编程控制,以满足您可能没有的业务需求。

问答

在本节中,您可以通过回答以下问题来回顾您对使用案例和IIF构造的理解程度。

问题1

CASE表达式有两种不同的语法变体:简单和搜索。下面的两个语句最好描述一个简单的和被搜索的案例表达式之间的区别(选择两个)

a、简单的CASE语法只支持平等操作符,而搜索的案例语法支持多个操作符

b、简单的CASE语法支持多个操作符,而搜索的案例语法只支持平等操作符

c、简单的CASE语法在WHEN子句之后指定了它的布尔表达式,而在CASE语句之后,搜索的CASE语法的左边是布尔表达式的左边,而在WHEN子句之后的布尔表达式的右边。

d、简单的CASE语法在后面的布尔表达式的左边

问题2

如果这个CASE表达式有多个当值为TRUE的子句,那么哪个子句被执行呢? a最后一个计算为TRUE的子句的表达式被执行。 b第一个当值为TRUE的子句的表达式被执行。 c然后执行所有计算为TRUEWHEN子句的表达式。 dELSE表达式被执行

问题3

一个CASE表达式或IIF函数有多少个嵌套级别?

A8

B10

C16

C32

回答:

问题1

答案是ad。一个简单的CASE语句只能使用相等的运算符,而搜索的CASE表达式可以处理多个运算符,以及复杂的布尔表达式。此外,简单的CASE语法在单词CASE和等号右边的右手部分之后,在单词后面加上了等号右边的左手部分。一个搜索的案例表达式必须在WHEN子句之后完成布尔操作(左手部分,操作符,右手部分)

问题2

正确的答案是b。如果多个子句的值为TRUE,那么SQL Server只执行第一个值为TRUE的子句的第一部分。当被评估为真的子句时,所有其他的子句都被跳过。

问题3

正确的答案是b。案例表达式和IIF函数只支持10个嵌套级别。

 

这篇文章是t-sql的阶梯的一部分:超越了基本的楼梯  


猜你喜欢

转载自blog.csdn.net/dennis_t/article/details/80155195