通往t - sql的阶梯:超越基本级别6:使用CASE表达式和IIF函数
在2016年4月20日被Gregory Larsen所创作,第一次出版于2014年4月9日。
这一系列:
这篇文章是阶梯系列的一部分:楼梯T-SQL:超越基础
下面就从他的楼梯T-SQL DML、Gregory Larsen覆盖的T-SQL语言如子查询更先进的方面。
很多时候,你需要写一个TSQL语句,能够返回基于另一个表达的评价不同的TSQL表达式。当你需要这种功能,你可以使用CASE表达式或IIF函数满足这个要求。在这篇文章中,我将回顾和IIF语法和显示你的情况下如何表达和IIF函数的例子。
理解CASE表达
Transact-SQL案例表达允许你将条件逻辑在你的TSQL代码。这个逻辑条件为您提供了一种方法来将不同的代码块,在你的TSQL语句可以执行取决于真实或虚假的逻辑条件评价。可以将多个条件表达式放置在单个case表达式中。当你有多个条件表达式在你的case,为真,第一个表达式将是由你的TSQL语句的代码块的评价。为了更好地理解case表达式的工作原理,我将回顾case表达式的语法,然后通过一些不同的例子。
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:CASE表达语法
通过查看图1中的case表达式的两种不同格式,您可以看到每个格式提供了一种不同的方式来识别确定表达式表达式结果的多个表达式中的一个。有两种情况,对每个子句执行布尔测试。与简单的案例表达的布尔测试左侧出现后的情况的话,被称为“input_expression”,右手边的布尔测试后的字时,被称为“表达”。与简单的案例表达“input_expression”和“when_expression”总是相等操作符之间的算子。而搜索的案例表达每个当条款将包含一个“boolean_expression”。这种“boolean_expression”可以用一个操作简单的布尔表达式,或一个复杂的布尔表达式在不同情况下。此外,搜索的case表达式可以使用布尔运算符的全套。
不管使用哪种格式,每个子句都按照它出现的顺序进行比较。case表达式的结果将基于第一个求值为true的子句。如果没有子句求值为true,则返回其他表达式。当省略其他子句并没有将子句求值为true时,返回空值。
列子中简单的数据
为了有一个表显示使用案例表达我将使用清单1中的脚本创建一个示例表命名 我的命令。如果您愿意跟随我的示例并在SQLServer实例上运行它们,可以在您选择的数据库中创建此表。
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.创建简单的我的命令表
用一个简单的CASE子句表达和其他的表达
为了演示简单的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:带有其他表达式的简单case表达式
让我先谈谈为什么这是一个简单的case表达式。如果你回顾清单2中的代码,你可以看到右后的字我指定的表达“年(orderdt)”,然后我跟着,由三种不同的表达式中每一个具有不同的指定年份,从2014开始。因为我指定了case和第一个表达式,当关键字告诉SQLServer时,这是一个简单的case表达式。
当我的简单表达式求值使用相等运算符(“=”)“年之间(订单)”的价值和不同的表达式。因此,清单1中的代码将显示“1”为“2014” orderdt 年值的行 yeartype 柱,或将显示“年2”行与 orderdt 年的“2013”或“3年”将显示行一个 orderdt 年“2012”。如果对 orderdt 年不匹配的表达式则else条件将显示“4年以后”。
在运行清单2中的代码时,得到结果1中显示的输出。
rderYear 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时的结果
用简单的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:没有其他子句的简单case表达式
清单3中的代码与清单2中的代码类似,但没有其他子句。在运行清单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 年遇见任何的条款条件时,SQL Server将显示“空”为该行的yeartype价值。
使用搜索的case表达式
在简单情况表达式中,基于等式运算符计算表达式。使用搜索的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:搜索case表达式
如果您查看清单4中的代码,您可以看到,当子句直接在两个子句之间没有文本的case子句之后。这告诉SQLServer这个搜索的case表达式。还要注意每个子句下面的布尔表达式。正如您所看到的,并非所有的布尔表达式都使用等号运算符,最后表达式使用小于(<)运算符。清单4中的case表达式在逻辑上与清单2中的case表达式相同。因此,在运行清单4中的代码时,它会生成与结果1相同的结果。
当表达式计算为true时,如果多个表达式返回什么表达式?
当表达式在单个case表达式中计算为true时,情况可能有所不同。当发生这种情况时,SQL Server将返回与第一个表达式相关联的结果表达式,该表达式计算为true。因此,子句的顺序将控制从case表达式返回的结果。
为了证明这让我们使用的情况下显示“200元”时, orderamt 在200美元的范围内,“100元”的 orderamt 是在100美元的范围, ”< 100美元订单”时, orderamt 小于100when美元的 orderamt 不属于任何一类,然后归类为“300美元及以上的订单”。让我们回顾一下清单5中的代码演示了当多个表达式的计算结果为真时,当试图将订单在一个 orderamt_category 值。
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中的结果,您可以看到每一个订单都是200或300以上的订单,我们知道这是不正确的。这是因为我只使用了不到(“<”)运营商简单地把订单导致多个表达式为真我表达。子句的顺序不允许返回正确的表达式。
通过重新排列我的从句,我可以得到我想要的结果。清单6中的代码与清单5相同,但我已经重新排列了子句,以便正确地分类我的订单。
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美元的采购订单。
有时您可能需要进行额外的测试,以便使用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:嵌套的CASE语句
清单7中的代码类似于清单6中的代码。唯一不同的是我增加了一个额外的案例表达是否在 myOrder 表顺序采用分期预付期权购买,这是只允许购买超过200美元。记住,在嵌套case表达式时,SQL Server只允许有10个嵌套级别。
可以使用case表达式的其他地方
到目前为止,我所有的例子,用案例表达将案例表达在一个TSQL SELECT语句的选择列表创建结果字符串。还可以在更新、删除和设置语句中使用case表达式。此外,case表达式可以与内、中、下和有子句一起使用。在清单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:在一个子句中使用CASE表达式
在清单8中,我只想回到我的命令从 表为在“1年”的行。为了实现这一点,我将与清单2中的WHERE子句使用相同的case表达式。我用案例表达左边部分的地方条件会产生不同的“年…”字符串基于 orderdt 柱。然后我测试的字符串,从案例表达产生是否等于价值“1年”,当它被一排将从 myOrder 表返回。请记住,我不建议使用一个case表达式使用一个类似“1年”的日期栏来选择日期,当有其他更好的方法,比如使用年份函数选择给定年份的行时。我只是在这里演示如何在WHERE子句中使用case语句。
简化的情况下使用IIf函数表达
与SQL Server 2012的介绍,加入微软的IIF函数。IIF函数可以被认为是一个捷径,case语句。在图2中你可以找到IIF函数的语法。
IIF ( boolean_expression, true_value, false_value )
图2:为IIF函数的语法
boolean_expression”是一个有效的布尔表达式,等同于真或假。当布尔表达式相当于一个真值,那么“true_value”表达的是执行。如果布尔表达式等同于虚假的那么“false_value”执行。就像案例表达的IIF函数可以嵌套到10层。
运用IIF函数的列子
演示如何IIf函数可以用来替代情况下的表达,让我们回顾一下使用搜索的案例表达清单9中的代码。
ELECT OrderAmt,
CASE
WHEN OrderAmt > 200 THEN ‘High $ Order‘
ELSE ‘Low $ Order‘ END AS OrderType
FROM MyOrder;
清单9:简单的case表达式示例
清单9中的代码只是一个单一的,用于确定是否 orderamt 或高或低的美元秩序的表达。如果在表达“orderamt > 200” 判断为真,那么 序型 值设置为“高达”。如果当表达式的值为false则“低美元秩序”设置为 序型 价值。
重新编写代码,使用IIf函数而不是一个案例的表达可以在清单10中发现。
SELECT OrderAmt,
IIF(OrderAmt > 200,
‘High $ Order‘,
‘Low $ Order‘) AS OrderType
FROM MyOrder;
清单10:使用IIF函数的例子
在清单10中可以看到为什么IIf函数被认为是一个案例表达速记版。这个词是“IIF取代(”字符串,“然后”条款是一个逗号,取代了“其他”条款是用逗号和“替换下场”替换为“)”。当布尔表达式”orderamt > 200”是真实的价值“高达”显示。当布尔表达式的orderamt > 200”进行虚假的那么“低阶”显示美元。如果运行清单9和10中的代码,就会看到它们都产生完全相同的输出。
嵌套的IIF函数的例子
就像案例表达SQL Server允许你嵌套Iif函数。清单11是嵌套的IIF函数的一个例子。
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子句嵌套。
总结
这样的表达与IIF函数允许你将表达逻辑在TSQL代码,将改变你的代码的结果基于一个表达式的计算结果。通过使用IIf函数和案例表达你可以有不同的代码块的执行取决于比较表达式的计算结果为true或false支持比较表达式。这样的表达与IIF函数为您提供编程控制以满足业务的需求,你可能没有。
问题和答案
在这一部分你可以回顾你们如何理解运用案例和IIF构建回答下列问题。
问题1:
case表达式有两种不同的语法变体:简单和搜索。下面哪两个陈述最好地描述了一个简单的和搜索的case表达式的区别(选择二)。
简单的案例语法只支持等式运算符,而搜索的案例语法支持多个运算符。
b.简单的案例语法支持多个操作符,而搜索的案例语法只支持等式运算符。
C.简单的case语法在后子句中指定了它的布尔表达式,而被搜索的case语法在case语句后面有布尔表达式的左边,和布尔子句后面的布尔表达式的右边。
简单的case语法在case语句后面和右边语句后面的布尔表达式的右边有布尔表达式的左边,而在后子句中,搜索的case表达式有它的布尔表达式。
问题2:
如果case表达式在判断为true的子句中有多个,则执行哪个子句?
A.执行到true的最后一个时子句的表达式。
执行第一个求值为true的子句的表达式。
执行时,将求值为true的子句的所有表达式都执行。
D.执行其他的表达
问题3:
有多少嵌套层次可以案例表达或IIF函数?
a.8
b.10
C.16
d.32
答案:
问题1:
答案是A和D。一个简单的case语句只能使用等号操作符,而搜索的case表达式可以处理多个操作符和复杂的布尔表达式。另外,简单的case语法有等号操作符的左边部分,在单词的后面和等号后面的右边操作符的右边部分。一个被搜索的case表达式必须完成布尔运算(左手部分、操作符、右部分)。
问题2:
正确的答案是B。如果多个子句求值为true,则SQL Server只执行第一个被求值为true的子句的当时部分。当所有被评估为true的子句被跳过时,所有其他子句都会被跳过。
问题3:
正确答案是B的表达与IIF函数只支持最多10个嵌套层次。
本文是对T-SQL 楼梯部分:超越基础 楼梯
注册到我们的RSS提要并在我们发布一个新级别的楼梯时得到通知!