- 积分
- 40165
- 好友
- 记录
- 主题
- 帖子
- 听众
- 收听
|
sql case使用方法
CASE 可能是 SQL 中被误用最多的关键字之一。虽然你可能以前用过这个关键字来创建字段,但是它还具有更多用法。例如,你可以在 WHERE
子句中使用 CASE。
首先让我们看一下 CASE 的语法。在一般的 SELECT 中,其语法如下:
SELECT =
CASE
WHEN [url=]THEN
WHEN THEN
ELSE
END [/url]
下面我们以一个例子来看看它的具体用法吧
[code=sql]--所有的功能列表
SELECT id,name,(CASE WHEN id=0 then ‘代理’ ELSE ‘正常用户’ end)AS stat FROM Agent [/code]
你甚至还可以组合这些选项,添加一个 ORDER BY 子句,如下所示:
[code=sql]USE pubs
GO
SELECT
CASE
WHEN price IS NULL THEN 'Unpriced'
WHEN price < 10 THEN 'Bargain'
WHEN price BETWEEN 10 and 20 THEN 'Average'
ELSE 'Gift to impress relatives'
END AS Range,
Title
FROM titles
GROUP BY
CASE
WHEN price IS NULL THEN 'Unpriced'
WHEN price < 10 THEN 'Bargain'
WHEN price BETWEEN 10 and 20 THEN 'Average'
ELSE 'Gift to impress relatives'
END,
Title
ORDER BY
CASE
WHEN price IS NULL THEN 'Unpriced'
WHEN price < 10 THEN 'Bargain'
WHEN price BETWEEN 10 and 20 THEN 'Average'
ELSE 'Gift to impress relatives'
END,
Title
GO
对于informix中形式有所不同,例子
select
case when td_acc1_no[1,3]='610' then get_contrast(td_acc1_no)
else get_contrast(td_td_acct_no)
end sx_acct_no
, sum(td_actu_amt) sx_bal
from dcc_tdacnacn where td_td_acct_no in ('6107111001014107111000050182',
'6107111001014107111000050168')
group by 1[/code]
注意,为了在 GROUP BY 块中使用 CASE,查询语句需要在 GROUP BY 块中重复 SELECT 块中的 CASE 块。
除了选择自定义字段之外,在很多情况下 CASE 都非常有用。再深入一步,你还可以得到你以前认为不可能得到的分组排序结果集。
下面我们来看看官方是怎么介绍的吧
计算条件列表,并返回多个可能的结果表达式之一。
CASE 表达式有两种格式:
- CASE 简单表达式,它通过将表达式与一组简单的表达式进行比较来确定结果。
- CASE 搜索表达式,它通过计算一组布尔表达式来确定结果。
这两种格式都支持可选的 ELSE 参数
CASE 可用于允许使用有效表达式的任意语句或子句。
例如,可以在 SELECT、UPDATE、DELETE 和 SET 等语句以及 select_list、IN、WHERE、ORDER BY 和 HAVING 等子句中使用 CASE。
[code=sql]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[/code]
input_expression
使用简单 CASE 格式时计算的表达式。
input_expression 是任意有效的表达式。
WHEN when_expression
使用简单 CASE 格式时要与 input_expression 进行比较的简单表达式。
when_expression 是任意有效的表达式。
input_expression 及每个 when_expression 的数据类型必须相同或必须是隐式转换的数据类型。
THEN result_expression
当 input_expression = when_expression 的计算结果为 TRUE 或者 Boolean_expression 等于 TRUE 时返回的表达式。
result expression 是任意有效的表达式。
ELSE else_result_expression
比较运算计算结果不为 TRUE 时返回的表达式。
如果忽略此参数且比较运算计算结果不为 TRUE,则 CASE 返回 NULL。
else_result_expression 是任意有效的表达式。
else_result_expression 及任何 result_expression 的数据类型必须相同或必须是隐式转换的数据类型。
WHEN Boolean_expression
使用 CASE 搜索格式时所计算的布尔表达式。
Boolean_expression 是任意有效的布尔表达式。
从 result_expressions 和可选 else_result_expression 的类型集中返回优先级最高的类型。
有关详细信息,请参阅数据类型优先级 (Transact-SQL)。
返回值
CASE 简单表达式:
CASE 简单表达式的工作方式如下:将第一个表达式与每个 WHEN 子句中的表达式进行比较,以确定它们是否等效。
如果这些表达式等效,将返回 THEN 子句中的表达式。
- 仅用于等同性检查。
- 计算 input_expression,然后按指定顺序对每个 WHEN 子句的 input_expression = when_expression 进行计算。
- 返回 input_expression = when_expression 的第一个计算结果为 TRUE 的 result_expression。
- 如果 input_expression = when_expression 的计算结果均不为 TRUE,则在指定了 ELSE 子句的情况下,SQL Server 数据库引擎将返回 else_result_expression;若没有指定 ELSE 子句,则返回 NULL 值。
CASE 搜索表达式:
- 按指定顺序对每个 WHEN 子句的 Boolean_expression 进行计算。
- 返回 Boolean_expression 的第一个计算结果为 TRUE 的 result_expression。
- 如果 Boolean_expression 计算结果不为 TRUE,则在指定 ELSE 子句的情况下数据库引擎将返回 else_result_expression;若没有指定 ELSE 子句,则返回 NULL 值。
SQL Server 仅允许在 CASE 表达式中嵌套 10 个级别。
CASE 表达式不能用于控制 Transact-SQL 语句、语句块、用户定义函数以及存储过程的执行流
有关控制流方法的列表,请参阅控制流语言 (Transact-SQL)。
CASE 语句按顺序评估其条件并在满足第一个条件时停止。
在某些情况下,将会先计算表达式,然后 CASE 语句会将表达式的结果作为其输入接收。
在计算这些表达式时可能会出现错误。
首先计算在 CASE 语句的 WHEN 参数中出现的聚合表达式,然后将结果提供给 CASE 语句。
例如,下面的查询将在生成 MAX 聚合的值时生成被零除错误。
在计算 CASE 表达式之前会出现这种情况。
[code=sql]WITH Data (value) AS
(
SELECT 0
UNION ALL
SELECT 1
)
SELECT
CASE
WHEN MIN(value) <= 0 THEN 0
WHEN MAX(1/value) >= 100 THEN 1
END
FROM Data ;[/code]
您应该仅依赖于标量表达式(包括返回标量的非相关子查询)的 WHEN 条件的计算顺序,而不应依赖于聚合表达式。
A.使用带有 CASE 简单表达式的 SELECT 语句
在 SELECT 语句中,CASE 简单表达式只能用于等同性检查,而不进行其他比较。
下面的示例使用 CASE 表达式更改产品系列类别的显示,以使这些类别更易于理解。
[code=sql]USE AdventureWorks2012;
GO
SELECT ProductNumber, Category =
CASE ProductLine
WHEN 'R' THEN 'Road'
WHEN 'M' THEN 'Mountain'
WHEN 'T' THEN 'Touring'
WHEN 'S' THEN 'Other sale items'
ELSE 'Not for sale'
END,
Name
FROM Production.Product
ORDER BY ProductNumber;
GO[/code]
[code=sql]USE AdventureWorks2012;
GO
SELECT ProductNumber, Category =
CASE ProductLine
WHEN 'R' THEN 'Road'
WHEN 'M' THEN 'Mountain'
WHEN 'T' THEN 'Touring'
WHEN 'S' THEN 'Other sale items'
ELSE 'Not for sale'
END,
Name
FROM Production.Product
ORDER BY ProductNumber;
GO[/code]
B.使用带有 CASE 搜索表达式的 SELECT 语句
在 SELECT 语句中,CASE 搜索表达式允许根据比较值替换结果集中的值。
下面的示例根据产品的价格范围将标价显示为文本注释。
[code=sql]USE AdventureWorks2012;
GO
SELECT ProductNumber, Name, "Price Range" =
CASE
WHEN ListPrice = 0 THEN 'Mfg item - not for resale'
WHEN ListPrice < 50 THEN 'Under $50'
WHEN ListPrice >= 50 and ListPrice < 250 THEN 'Under $250'
WHEN ListPrice >= 250 and ListPrice < 1000 THEN 'Under $1000'
ELSE 'Over $1000'
END
FROM Production.Product
ORDER BY ProductNumber ;
GO[/code]
C.在 ORDER BY 子句中使用 CASE
下面的示例在 ORDER BY 子句中使用 CASE 表达式,以根据给定的列值确定行的排序顺序。
在第一个示例中,会计算 HumanResources.Employee 表中 SalariedFlag 列的值。
SalariedFlag 设置为 1 的员工将按 EmployeeID 以降序顺序返回。
SalariedFlag 设置为 0 的员工将按 EmployeeID 以升序顺序返回。
在第二个示例中,当 CountryRegionName 列等于“United States”时,结果集会按 TerritoryName 列排序,对于所有其他行则按 CountryRegionName 排序。
D.在 UPDATE 语句中使用 CASE
下面的示例在 UPDATE 语句中使用 CASE 表达式,以确定为 SalariedFlag 设置为 0 的员工的 VacationHours 列所设置的值。
如果 VacationHours 减去 10 小时后会得到一个负值,则 VacationHours 将增加 40 小时;否则 VacationHours 将增加 20 小时。
OUTPUT 子句用于显示前后的休假时间值。
[code=sql]USE AdventureWorks2012;
GO
UPDATE HumanResources.Employee
SET VacationHours =
( CASE
WHEN ((VacationHours - 10.00) < 0) THEN VacationHours + 40
ELSE (VacationHours + 20.00)
END
)
OUTPUT Deleted.BusinessEntityID, Deleted.VacationHours AS BeforeValue,
Inserted.VacationHours AS AfterValue[/code]WHERE SalariedFlag = 0;
E.在 SET 语句中使用 CASE
下面的示例在表值函数 dbo.GetContactInfo 中的 SET 语句中使用 CASE 表达式。
在 AdventureWorks2012
数据库中,与人员有关的所有数据都存储在 Person.Person 表中。
例如,该人员可以是员工、供应商代表或消费者。
该函数将返回给定 BusinessEntityID 的名字与姓氏以及该人员的联系人类型。SET 语句中的 CASE 表达式将根据该 BusinessEntityID 列是存在于
Employee、Vendor 还是存在于 Customer 表中来确定要为 ContactType 列显示的值。
[code=sql]USE AdventureWorks2012;
GO
CREATE FUNCTION dbo.GetContactInformation(@BusinessEntityID int)
RETURNS @retContactInformation TABLE
(
BusinessEntityID int NOT NULL,
FirstName nvarchar(50) NULL,
LastName nvarchar(50) NULL,
ContactType nvarchar(50) NULL,
PRIMARY KEY CLUSTERED (BusinessEntityID ASC)
)
AS
-- Returns the first name, last name and contact type for the specified contact.
BEGIN
DECLARE
@FirstName nvarchar(50),
@LastName nvarchar(50),
@ContactType nvarchar(50);
-- Get common contact information
SELECT
@BusinessEntityID = BusinessEntityID,
@FirstName = FirstName,
@LastName = LastName
FROM Person.Person
WHERE BusinessEntityID = @BusinessEntityID;
SET @ContactType =
CASE
-- Check for employee
WHEN EXISTS(SELECT * FROM HumanResources.Employee AS e
WHERE e.BusinessEntityID = @BusinessEntityID)
THEN 'Employee'
-- Check for vendor
WHEN EXISTS(SELECT * FROM Person.BusinessEntityContact AS bec
WHERE bec.BusinessEntityID = @BusinessEntityID)
THEN 'Vendor'
-- Check for store
WHEN EXISTS(SELECT * FROM Purchasing.Vendor AS v
WHERE v.BusinessEntityID = @BusinessEntityID)
THEN 'Store Contact'
-- Check for individual consumer
WHEN EXISTS(SELECT * FROM Sales.Customer AS c
WHERE c.PersonID = @BusinessEntityID)
THEN 'Consumer'
END;
-- Return the information to the caller
IF @BusinessEntityID IS NOT NULL
BEGIN
INSERT @retContactInformation
SELECT @BusinessEntityID, @FirstName, @LastName, @ContactType;
END;
RETURN;
END;
GO
SELECT BusinessEntityID, FirstName, LastName, ContactType
FROM dbo.GetContactInformation(2200);
GO
SELECT BusinessEntityID, FirstName, LastName, ContactType
FROM dbo.GetContactInformation(5);[/code]
F.在 HAVING 子句中使用 CASE
下面的示例在 HAVING 子句中使用 CASE 表达式,以限制由 SELECT 语句返回的行。
该语句将返回 HumanResources.Employee 表中针对每个职位的最高每小时薪金。
HAVING 子句将职位限制为两类员工:一是最高每小时薪金超过 40 美元的男性员工,二是最高每小时薪金超过 42 美元的女性员工。
[code=sql]
USE AdventureWorks2012;
GO
SELECT JobTitle, MAX(ph1.Rate)AS MaximumRate
FROM HumanResources.Employee AS e
JOIN HumanResources.EmployeePayHistory AS ph1 ON e.BusinessEntityID = ph1.BusinessEntityID
GROUP BY JobTitle
HAVING (MAX(CASE WHEN Gender = 'M'
THEN ph1.Rate
ELSE NULL END) > 40.00
OR MAX(CASE WHEN Gender = 'F'
THEN ph1.Rate
ELSE NULL END) > 42.00)
ORDER BY MaximumRate DESC;
[/code]
|
|