今天帮朋友调了一个网站,无意中翻了一个sp,看到了一段很长的select语句,这个select语句之所以长,是因为有好几个一般复杂的case语句跟在select的后面。我们摘取其中的一个字段的逻辑规则和数据来做我们的测试数据:
create table tbl (id int, type_a int)
insert into tbl values (1000,1000)
insert into tbl values (999,999)
insert into tbl values (998,998)
insert into tbl values (997,997)
insert into tbl values (996,996)
insert into tbl values (995,null)
insert into tbl values (994,null)
insert into tbl values (993,null)
insert into tbl values (992,null)
insert into tbl values (991,null)
逻辑非常简单:当type_a为997或null的时候,我们要让输出的type_a字段值为0。
OK,这个SQL语句当然有多种写法,朋友的sql是这样写的:
select
case
when (type_a is null or type_a=997) then 0
else type_a
end as type_a
from tbl
如果需要控制的字段一多,那这个及时已经使用了缩进的select也看起来很复杂了,时间久了想改动这个sp的逻辑就有些吃力了,我们常常在做计划时会说“半小时搞定这个问题”,但是往往在做的时候都会超过这个时间,原因就在于我们总有从一团乱麻中找到入手点。复杂的代码和逻辑往往是解决问题中难啃的骨头。那么有什么好办法优化一下吗?
select coalesce(nullif(type_a,997),0) as type_a from tbl
Well,上面写了6行的sql就被这1行所替代了。
nullif接受两个参数,如果两个参数相等,那么返回null,否则返回第一个参数
coalesce接受N个参数,返回第一个不为null的参数
So,当您遇到处理一个如下所示的计算工资的问题的时候,不妨这样来解决:create table salary (e_id uniqueidentifier, byMonth int, byHalfYear int, byYear int)
insert into salary values (newid(),9000,null,null)
insert into salary values (newid(),null,60000,null)
insert into salary values (newid(),null,null,150000)
每个雇员有3种薪资计算方式(按月,按半年,按年)来发放工资,如果我们想统计每个员工的年薪,那这样一句就够了:
select e_id,coalesce(byMonth*12,byHalfYear*2,byYear) as salary_amount from salary
结果:
e_id salary_amount
------------------------------------ -------------
8935330D-2B73-4FEF-941A-768D7A8CCB6C 108000
52A3CE16-74FD-4D5D-BB4F-F5F67A1E9D2F 120000
06B6B924-EAB2-4187-B733-EBB56B62E793 150000
参考:
COALESCE (Transact-SQL)
NULLIF (Transact-SQL)
附:
SQL Server 2005中的except/intersect和outer apply