sql语句的case-end语句的疑似bug经历

给客服部做客户分级服务的客户信息设置。要求根据客户历史积分、客户投资成本两个指标对客户进行评级。客户级别分为4级:
    级别1-integral介于[0, 8188]或者investcost介于[ 0, 50000]
    级别2-integral介于[8188, 15888]或者investcost介于[ 50000, 500000]
    级别3-integral介于[15888, 98888]或者investcost介于[ 500000, 100000]
    级别4-integral介于[15888, 无穷大]或者investcost介于[ 100000, 无穷大]

没仔细细想,将两个表联查,并根据integral和investcost两个字段,生成一个levelsign字段。sql代码如下:
CREATE TABLE tcustlevel AS
SELECT t.customerid, --t.customertypesign, t.customerlevelsign, t.customerintegral, nvl(t2.investcost, 0) investcost,
    (case
    when (t.customerintegral >= 0 AND t.customerintegral < 8188) OR (nvl(t2.investcost, 0) >= 0 AND nvl(t2.investcost, 0) < 50000)
        then '1'
    when (t.customerintegral >= 8188 AND t.customerintegral < 15888) OR (nvl(t2.investcost, 0) >= 50000 AND nvl(t2.investcost, 0) < 500000)
        then '2'
    when (t.customerintegral >= 15888 AND t.customerintegral < 98888) OR (nvl(t2.investcost, 0) >= 500000 AND nvl(t2.investcost, 0) < 1000000)
        then '3'
    when (t.customerintegral >= 98888) OR (nvl(t2.investcost, 0) >= 1000000)
        THEN '4'
    end) levelsign--, t.*, t2.*
--SELECT COUNT(*)    
FROM tcustintegral t, tcustcost t2
WHERE 1 = 1
AND t.customerid = t2.customerid(+);
后来实际用到levelsign数据后,才发现,这样写存在一个大bug!!!比如当(integral, investcost) =(15234,792561)时,levelsign应该取3,但结果取值为2。

突然发现以前解决过类似的问题,这是由于case-end的顺序执行和A or B的条件判断两个因素造成的。case-end顺序执行子句中的每一个条件,满足则输出结果并结束后续子句的执行,否则执行下一个子句(即判断条件)。按照上面给定的值,在第2个子句(t.customerintegral >= 8188 AND t.customerintegral < 15888) OR (nvl(t2.investcost, 0) >= 50000 AND nvl(t2.investcost, 0) < 500000)时条件为真,所以输出'2',忽略后续余下子句中的判断条件。

鉴于本问题中的情况,耍了个小伎俩,将执行顺序颠倒,就可以避免错误,输出正确结果,唯一的缺憾是非最优美的解决方案(即万一后来人维护该段代码时,改变了子句顺序,则又会出错了)。所以只好在该段代码头上加上了一段提示性的注释,特别提醒注意。
CREATE TABLE tcustlevel AS
SELECT t.customerid, --t.customertypesign, t.customerlevelsign, t.customerintegral, nvl(t2.investcost, 0) investcost,
    (case
    when (t.customerintegral >= 98888) OR (nvl(t2.investcost, 0) >= 1000000)
        THEN '4'
    when (t.customerintegral >= 15888 AND t.customerintegral < 98888) OR (nvl(t2.investcost, 0) >= 500000 AND nvl(t2.investcost, 0) < 1000000)
        then '3'
    when (t.customerintegral >= 8188 AND t.customerintegral < 15888) OR (nvl(t2.investcost, 0) >= 50000 AND nvl(t2.investcost, 0) < 500000)
        then '2'
    when (t.customerintegral >= 0 AND t.customerintegral < 8188) OR (nvl(t2.investcost, 0) >= 0 AND nvl(t2.investcost, 0) < 50000)
        then '1'
    end) levelsign--, t.*, t2.*
--SELECT COUNT(*)    
FROM tcustintegral t, tcustcost t2
WHERE 1 = 1
AND t.customerid = t2.customerid(+)

纵观本次错误经历,再次验证coding时要想不冒bug真得很难!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值