1. 程式人生 > >樓梯T-SQL:超越基礎6級:使用CASE表達式和IIF函數

樓梯T-SQL:超越基礎6級:使用CASE表達式和IIF函數

sim 等號 sql語句 arc 要求 sql代碼 -- express 但是

從他的樓梯到T-SQL DML,Gregory Larsen涵蓋了更多的高級方面的T-SQL語言,如子查詢。

有時您需要編寫一個可以根據另一個表達式的評估返回不同的TSQL表達式的單個TSQL語句。當您需要這種功能時,您可以使用CASE表達式或IIF函數來滿足此要求。在本文中,我將回顧CASE和IIF語法,並向您展示CASE表達式和IIF函數的示例。

了解CASE表達
Transact-SQL CASE表達式允許您在TSQL代碼中放置條件邏輯。此條件邏輯為您提供了一種在TSQL語句中放置不同代碼塊的方法,該語句可以根據條件邏輯的TRUE或FALSE評估來執行。您可以在單個CASE表達式中放置多個條件表達式。當CASE子句中有多個條件表達式時,第一個計算結果為TRUE的表達式將是由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
2017/10/31 14:42:56

圖1:CASE表達式語法

通過查看圖1中CASE表達式的兩種不同格式,您可以看到每種格式如何提供不同的方法來標識確定CASE表達式結果的多個表達式之一。對於兩種類型的CASE,對每個WHEN子句執行布爾測試。使用簡單CASE表達式,布爾測試的左側出現在CASE單詞之後,稱為“input_expression”,右側的“WHEN”表示右側,稱為“when expression”。使用簡單CASE表達式,“input_expression”和“when_expression”之間的運算符始終是相等運算符。而搜索到的CASE表達式,每個WHEN子句將包含一個“Boolean_expression”。這個“Boolean_expression”可以是一個帶有單個運算符的簡單布爾表達式,也可以是具有許多不同條件的復雜布爾表達式。另外,搜索到的CASE表達式可以使用完整的布爾運算符集。

無論使用哪種CASE格式,每個WHEN子句按其出現順序進行比較。 CASE表達式的結果將基於評估為TRUE的第一個WHEN子句。如果沒有WHEN子句求值為TRUE,則返回ELSE表達式。當ELSE子句被省略且WHEN子句的計算結果為TRUE時,將返回NULL值。

示例數據樣本
為了有一個表來演示使用CASE表達式,我將使用清單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);
2017/10/31 14:44:39

清單1:創建示例表MyOrder

使用簡單的CASE表達式與WHEN和ELSE表達式
為了演示簡單的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表達式

讓我先談一談為什麽這是一個簡單的CASE表達。如果您查看清單2中的代碼,您可以看到緊跟在CASE字之後,我指定了表達式“YEAR(OrderDT)”,然後我按照三個不同的WHEN表達式,每個具有不同的年份指定,從2014開始。因為我指定CASE和第一個WHEN關鍵字之間的表達式告訴SQL Server這是一個簡單的CASE表達式。

當我簡單的CASE表達式被評估時,它使用“YEAR(OrderDate)”值和不同的WHEN表達式之間的等號運算符(“=”)。因此,清單1中的代碼將為OrderType列顯示“Year 1”,其中OrderDT年值為“2014”,否則對於OrderDT年份為“2013”??的行將顯示“Year 2”,或者將為OrderDT年份為“2012”的行顯示“Year 3”。如果OrderDT的年份與WHEN表達式不匹配,則ELSE條件將顯示“Year 4 and beyond”。

當我運行清單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
2017/10/31 14:46:16
結果1:運行清單2時的結果

使用沒有ELSE表達式的簡單CASE表達式
讓我運行清單3中的代碼,它將顯示一個Simple CASE表達式沒有ELSE子句時會發生什麽。

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;。
2017/10/31 14:48:58

清單3:沒有ELSE子句的簡單CASE表達式

清單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將為該行的YearType值顯示“NULL”。

使用搜索的CASE表達式
在簡單的CASE表達式中,WHEN表達式基於等式運算符進行評估。 使用搜索到的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中的代碼,您可以看到WHEN子句直接在CASE子句之後,兩個子句之間沒有文本。這告訴SQL Server這是一個搜索的CASE表達式。還要註意每個WHEN子句後面的布爾表達式。正如你可以看到並不是所有這些布爾表達式都使用等號運算符,最後一個WHEN表達式使用小於(“<”)運算符。清單4中的CASE表達式在邏輯上與清單2中的CASE表達式相同。因此,當我運行清單4中的代碼時,會產生與結果1所示相同的結果。

如果多個WHEN表達式求值為TRUE,則返回什麽表達式?
在單個CASE表達式中可能會有不同WHEN表達式求值為TRUE的情況。當這種情況發生時,SQL Server將返回與第一個WHEN表達式關聯的結果表達式,該WHEN表達式計算結果為true。因此,如果多個WHEN子句評估為TRUE,則WHEN子句的順序將控制從CASE表達式返回的結果。

為了證明這一點,當OrderAmt在$ 200範圍內時,我們使用CASE表達式顯示“200美元訂單”,當OrderAmt在$ 100範圍內時,“100美元訂單”,當OrderAmt小於$ 100時,“100美元訂單”當OrderAmt不屬於這些類別時,將該訂單分類為“300美元及以上訂單”。我們來看看清單5中的代碼,以演示當嘗試將訂單分類到其中一個OrderAmt_Category值時,當多個WHEN表達式求值為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:多個WHEN表達式求值為TRUE的示例

當我運行清單5中的代碼時,我得到Result 3中的輸出。
2017/10/31 14:51:01

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及以上的訂單,我們知道這是不正確的。 這是因為我僅使用少於(“<”)運算符來簡單地對在CASE表達式中導致多個WHEN表達式求值為TRUE的Orders進行分類。 WHEN子句的排序不允許返回正確的表達式。

通過重新排序我的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類似的代碼,但WHEN子句的順序不同

當我運行清單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中的輸出,您可以看到,通過更改WHEN表達式的順序,我得到每個訂單的正確結果。

嵌套CASE表達式
有時您可能需要進行其他測試,以使用CASE表達式進一步分類數據。 當這種情況發生時,您可以使用嵌套的CASE表達式。 清單7中的代碼顯示了嵌套CASE表達式以進一步分類MyOrder表中的訂單的示例,以確定訂單是否超過$ 200時是否使用Layaway值購買訂單。

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中的代碼。唯一的區別是我添加了一個額外的CASE表達式,以查看MyOrder表中的訂單是否使用Layaway選項購買,只能在超過$ 200的購買上購買。 嵌套CASE表達式時請牢記SQL Server只允許最多10個嵌套級別。

其他可以使用CASE表達式的地方
到目前為止,我的所有示例都使用CASE表達式通過將CASE表達式放在TSQL SELECT語句的選擇列表中來創建結果字符串。 您還可以在UPDATE,DELETE和SET語句中使用CASE表達式。 另外,CASE表達式可以與IN,WHERE,ORDER BY和HAVING子句一起使用。 在清單8中,我使用了表示WHERE子句的CASE。

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子句中使用CASE表達式

在清單8中,我只想從MyOrder表中的“Year 1”行返回一個訂單。為了實現這一點,我將在WHERE子句中放置與清單2中所使用的相同的CASE表達式。我使用CASE表達式作為WHERE條件的左側部分,因此它將根據OrderDT列生成不同的“Year ...”字符串。然後我測試了從CASE表達式生成的字符串,以查看它是否等於值“Year 1”,當它是從MyOrder表返回的行。請記住,當有其他更好的方法,如使用YEAR功能選擇給定年份的行時,不建議使用CASE表達式從日期列中選擇日期。我只在這裏說明如何在WHERE子句中使用CASE語句。

使用IIF功能快速切換CASE表達式
隨著SQL Server 2012的推出,微軟增加了IIF功能。 IIF函數可以被認為是CASE語句的快捷方式。在圖2中,您可以找到IIF函數的語法。

IIF ( boolean_expression, true_value, false_value )

圖2:IIF功能的語法

“Boolean_expression”是一個有效的布爾表達式,相當於TRUE或FALSE。 當布爾表達式等於TRUE值時,執行“true_value”表達式。 如果布爾表達式等於FALSE,則執行“false_value”。 就像CASE表達式一樣,IIF函數可以嵌套多達10個級別。

使用IIF的例子
為了演示如何使用IIF函數來替換CASE表達式,我們來看看使用清單9中搜索到的CASE表達式的代碼。

SELECT OrderAmt,
CASE
WHEN OrderAmt > 200 THEN ‘High $ Order‘
ELSE ‘Low $ Order‘ END AS OrderType
FROM MyOrder;

清單9:簡單的CASE表達式示例

清單9中的代碼只有一個WHEN表達式,用於確定OrderAmt是高或低美元訂單。 如果WHEN表達式“OrderAMT> 200”計算結果為TRUE,則OrderType值設置為“High $ Order”。 如果WHEN表達式計算為FALSE,則為OrderType值設置“Low $ Order”。

使用IIF函數而不是CASE表達式的重寫代碼可以在清單10中找到。

SELECT OrderAmt,
IIF(OrderAmt > 200,
‘High $ Order‘,
‘Low $ Order‘) AS OrderType
FROM MyOrder;
2017/10/31 14:55:12

清單10:使用IIF函數的示例

通過查看清單10,您可以看到為什麽IIF函數被認為是CASE表達式的簡寫版本。 CASE替換為“IIF(”字符串,“THEN”子句用逗號替換,“ELSE”子句用逗號替換,“END”替換為“)”。 當布爾表達式“OrderAmt> 200”為TRUE時,顯示值“High $ Order”。 當布爾表達式“OrderAmt> 200”被評估為FALSE時,顯示“低$訂單”。 如果運行清單9和10中的代碼,您將看到它們都產生完全相同的輸出。

嵌套IIF功能的示例
就像CASE表達式一樣,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功能一樣,存在限制。以下是有關CASE和IIF結構的一些限制。

CASE表達限制:

•CASE表達式中最多只能有10個嵌套級別。
•CASE表達式不能用於控制TSQL語句的執行流程。
IIF功能限制:

•您只能擁有多達10級的嵌套IIF子句。
概要
CASE表達式和IIF函數允許您將表達式邏輯放在TSQL代碼中,這將基於表達式的計算結果來更改代碼的結果。通過使用IIF函數和CASE表達式支持的比較表達式,可以根據比較表達式的計算結果為TRUE還是FALSE,執行不同的代碼塊。 CASE表達式和IIF函數為您提供編程控制,以滿足您可能沒有的業務需求。

問題和答案
在本節中,您可以回答以下問題,了解如何使用CASE和IIF構造。

問題1:
CASE表達式有兩種不同的語法變體:Simple和Searched。下面哪兩個語句最好地描述了簡單和搜索的CASE表達式(Pick 2)之間的區別。

a。簡單CASE語法僅支持等式運算符,而Searched CASE語法支持多個運算符
b。簡單CASE語法支持多個運算符,而Searched CASE語法僅支持等式運算符
c。簡單CASE語法在WHEN子句之後指定了布爾表達式,而Searched CASE語法在CASE語句之後具有布爾表達式的左側,WHEN子句後面的布爾表達式的右側。
d。簡單CASE語法在CASE語句之後具有布爾表達式的左側,WHEN子句後面的布爾表達式的右側,而Searched CASE表達式在WHEN子句之後具有其布爾表達式

問題2:
如果CASE表達式有多個WHEN子句評估為TRUE,執行THEN / ELSE子句?

執行評估為TRUE的最後一個WHEN子句的THEN表達式。
b。執行計算為TRUE的第一個WHEN子句的THEN表達式。
c。執行評估為TRUE的WHEN子句的所有THEN表達式。
執行d.THE ELSE表達式
問題3:
CASE表達式或IIF函數有多少嵌套級別?

A.8
B.10
C.16
草32
回答:
問題1:
答案是a和d。簡單的CASE語句只能使用相等運算符,而Searched CASE表達式可以處理多個運算符以及復雜的布爾表達式。另外,簡單CASE語法具有緊靠單詞CASE之後的等式運算符的左手部分,並且等於WHEN之後的等式運算符的右手部分。搜索的CASE表達式必須在WHEN子句之後完成布爾運算(左手部分,運算符,右手部分)

問題2:
正確的答案是b。如果多個WHEN子句求值為TRUE,則SQL Server僅執行第一個WHEN子句的THEN部分,該WHEN子句的計算結果為TRUE。被評估為TRUE的任何其他WHEN子句的所有其他THEN子句將被跳過。
2017/10/31 14:57:31
我的小秘 2017/10/31 14:57:31

問題3:
正確的答案是b。 CASE表達式和IIF功能僅支持最多10個嵌套級別

樓梯T-SQL:超越基礎6級:使用CASE表達式和IIF函數