CASE 表达
CASE 表达式允许根据对一个或多个条件的评估来选择表达式。
搜索条件:
简单句:
通常, 条件表达式的值是第一个(最左边) 当条件子句求值为真时的结果表达式的值。 如果没有满足为真的情况,且存在ELSE关键字,则结果为结果表达式的值或NULL。 如果没有满足为真的情况,且没有ELSE关键字,则结果为NULL。 当某个情况评估为未知(因为为空值)时,该情况为非真,因此与评估为假的情况处理方式相同。
- 当……时搜索
- 指定一个搜索条件 ,该条件应用于每行或每组用于评估的表格数据,以及当条件为真时的结果。
进行配对比较。 每对隐式变量的规则与基本谓词相同。 当条件子句对字符串和数字搜索条件执行隐式转换。
- 简单句
- 指定在第一个“WHEN”关键字之前, 表达式的值与“WHEN”关键字之后的每个表达式的值进行相等性测试。 它还指定了当条件为真时的结果。
第一个“WHEN”关键字之前的表达式数据类型必须与每个“WHEN”关键字之后的表达式数据类型兼容。 任何表达式的数据类型不能是CLOB、DBCLOB或BLOB。 此外,第一个“WHEN”关键字之前的表达式不能包含非确定性函数或外部动作。
- 结果表达式或 NULL
- 指定THEN和ELSE关键字后面的值。 它指定了当搜索条件或简单条件为真时,或者当所有条件都不为真时,结果是什么。 CASE 表达式中必须至少有一个结果表达式具有定义的数据类型。 不能为每种情况指定NULL。
所有结果表达式必须具有兼容的数据类型。 结果的属性根据结果数据类型规则中描述的规则确定。 当结果是一个字符串时,其属性包括CCSID。 有关如何确定 CCSID 的规则,请参阅字符串的编码方案和 CCSID 规则。
- search-condition
- 指定行或表数据组为真、假或未知的条件。 搜索条件可以是谓词,包括包含全选(标量或非标量)或行值表达式的谓词。如果搜索条件中的搜索时间子句指定了包含全选(fullselect)的量化谓词或IN谓词,则 CASE 表达式不能用于以下情况:
- 选择列表
- INSERT或MERGE语句的VALUES子句
- UPDATE、MERGE或DELETE语句的SET或赋值子句
- SET或赋值语句的右侧
- 列掩码或行权限的定义
如果搜索条件中的搜索时间子句指定了EXISTS谓词,则 CASE 表达式不能用于以下情况:- INSERT或MERGE语句的VALUES子句
- SET或赋值语句的右侧
SIGNAL语句的诊断字符串表达式
ORDER BY子句或GROUP BY子句
- 结束
- 句子的结尾。
如果 CASE 表达式位于导出最终结果表的选定列表中,并且如果简单条件子句或搜索条件子句引用了带有全选的基本谓词,则列掩码不能应用于导出 CASE 表达式结果的THEN子句中的列。
如果 CASE 表达式在导出最终结果表的选定列表中,并且如果简单条件语句或搜索条件语句引用了已激活列访问控制的列,则列掩码不能应用于该列,并返回错误。
如果 CASE 表达式出现在UPDATE、MERGE或DELETE语句的SET子句中,INSERT或MERGE语句的VALUES子句中,或INSERT from fullselect语句的fullselect中,并且如果简单条件子句或搜索条件子句引用了已激活列访问控制的列,则忽略该列的列访问控制。
两个标量函数NULLIF和COALESCE专门用于处理 CASE 提供的功能子集。 下表显示了使用 CASE 或这些函数的等效表达式。
| CASE 表达式 | 同义表达 |
|---|---|
CASE WHEN THEN NULL ELSE END e1=e2
e1 |
NULLIF( e1,e2 ) |
CASE 当 不为空时, ,否则, ,否则, ,结束 e1
e1 e2 |
COALESCE( e1,e2 ) |
CASE 当 不为空时, ,否则, ,否则,COALESCE( ),END e1
e1e2,...,eN |
COALESCE( e1,e2,...,eN ) |
示例1(简单条件句 ):假设在雇员表中,部门编号的第一个字符代表组织中的部门。 使用 CASE 表达式列出每位员工所属部门的完整名称。
SELECT EMPNO, LASTNAME,
CASE SUBSTR(WORKDEPT,1,1)
WHEN 'A' THEN 'Administration'
WHEN 'B' THEN 'Human Resources'
WHEN 'C' THEN 'Design'
WHEN 'D' THEN 'Operations'
END
FROM EMPLOYEE;示例 2(搜索条件 ):您还可以使用 CASE 表达式来避免
除数为零的错误。 从“员工”表中,找到所有收入中超过25%来自佣金,但并非完全以佣金形式获得报酬的员工:
SELECT EMPNO, WORKDEPT, SALARY+COMM FROM EMPLOYEE
WHERE (CASE WHEN SALARY=0 THEN 0
ELSE COMM/(SALARY+COMM)
END) > 0.25;示例 3(搜索条件 ):您可以使用 CASE 表达式来避免
零除法的错误。 以下查询显示累加或求和操作。 在第一个查询中, Db2 在执行 CASE 语句之前执行了除法运算,结果出现了错误。
SELECT REF_ID,PAYMT_PAST_DUE_CT,
CASE
WHEN PAYMT_PAST_DUE_CT=0 THEN 0
WHEN PAYMT_PAST_DUE_CT>0 THEN
SUM(BAL_AMT/PAYMT_PAST_DUE_CT)
END
FROM PAY_TABLE
GROUP BY REF_ID,PAYMT_PAST_DUE_CT;然而,如果SUM聚合函数中包含 CASE 表达式,则 CASE 表达式可以防止错误。 在下面的查询中, CASE 表达式排除了不需要的除法,因为 CASE 操作在除法之前执行。 SELECT REF_ID,PAYMT_PAST_DUE_CT,
SUM(CASE
WHEN PAYMT_PAST_DUE_CT=0 THEN 0
WHEN PAYMT_PAST_DUE_CT>0 THEN
BAL_AMT/PAYMT_PAST_DUE_CT
END)
FROM PAY_TABLE
GROUP BY REF_ID,PAYMT_PAST_DUE_CT;示例4: 本示例说明如何通过 CASE 表达式对查询结果进行分组,而无需重新输入表达式。 使用示例员工表,找出最高、最低和平均薪资。 假设您想将一些部门合并到同一个组中,而不是为每个部门寻找这些值。
SELECT CASE_DEPT,MAX(SALARY),MIN(SALARY),AVG(SALARY)
FROM (SELECT SALARY,CASE WHEN WORKDEPT = 'A00' OR WORKDEPT = 'E21'
THEN 'A00_E21'
WHEN WORKDEPT = 'D11' OR WORKDEPT = 'E11'
THEN 'D11_E11'
ELSE WORKDEPT
END AS CASE_DEPT
FROM DSN8C10.EMP) X
GROUP BY CASE_DEPT;