DB2使用小结(五):使用Case语句
http://qml007.blog.163.com/blog/static/5134854200610159394453/
应用难点技巧:使用Case让你的SQL语句有条件的执行
我们在编写SQL语句时,常常遇到希望SQL能够按条件执行的情况。这里的条件不是指Where子句中的条件,而是指让DB2根据条件执行SQL的语句块。大多数情况下我们可以使用case来实现。
例如,我们希望从员工表中查出员工的工资情况,如果小于20000,则标志为low,20000到50000间为middle,否则为high。一般大家会想到先取出工资数据然后在Java代码中做判断,但我们也可以在SQL中完成上述操作。如下例:
select empno, sex, salary,
case
when salary < 20000 then 'low'
when salary >=20000 and salary <50000 then 'middle'
else 'high'
end as salaryclass
from employee
类似的,如果想在SQL语句中把性别翻译成文字,也可以用case实现,注意这两条SQL语句使用了不同的case表达式写法:
select empno,
case sex
when 'M' then 'male'
when 'F' then 'female'
else 'invalid'
end,
salary
from employee
Case不但能够在Select子句中使用,在From子句和Where子句中同样可以使用。下面是在Where子句中使用的一个例子:
select empno, sex, age
from employee
where
case sex
when 'M' then 55
when 'F' then 50
end > age
在From子句中使用的例子极为少见,下面是一个极端的例子。在合同表ctrct_list、客户表customer和订单表quote中都有合同号字段,但订单表中的合同号可能为空。要求查询出订单表订单id和合同号,如订单表中合同号为空的话,查出客户表中相应的合同号。
select distinct
q.quote_id,
case rtrim(coalesce(q.ctrct_num, ''))
when '' then rtrim(coalesce(c.ctrct_num, ''))
else rtrim(coalesce(q.ctrct_num, ''))
end ctrct_num
from
(quote q
left outer join customer c
on q.sold_to_cust_num = c.cust_num)
inner join ctrct_list cl
on cl.cust_num = q.sold_to_cust_num
and cl.ctrct_num = (
case rtrim(coalesce(q.ctrct_num, ''))
when '' then c.ctrct_num
else q.ctrct_num
end
)
有时让SQL语句有条件的执行也可以不使用case。下面是一个例子:
select *
from EMPLOYEE
WHERE
((job='MANAGER') AND vMgrFlag=1)
or
((job='DESIGNER' or job='ANALYST') AND vTechFlag =1)
or
((job='CLERK' or job='OPERATOR') AND vOfficeFlag=1)
此SQL可以要求根据标志位的不同选择出不同类型的雇员。各个标志位在执行SQL前应提前设置好。这种方法可以在某些情况下将动态SQL改写为静态SQL,因此在编写存储过程时非常实用。但要指出的是,DB2的查询优化器不可能将这种SQL也优化得非常高效,因此在数据量比较大时可能会带来性能问题。开发人员需要在编写完成后使用实际数据测试,必要的话进行性能优化。
此篇文章没有完全解决问题,经过查询,以下代码将问题解决
动态匹配查询条件的问题,如果MY_NAME==null那么忽略查询条件
MY_NAME = CASE :name WHEN 'null' THEN MY_NAME ELSE :name END
当null 值,MY_NAME =MY_NAME 相当于忽略