今天帮朋友调了一个网站,无意中翻了一个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 )
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
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 )
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
-- ---------------------------------- -------------
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