面对支公司和事业部反应的问题,我逐渐要求自己独立找答案,独立解决问题——这毕竟会是业务经办与业务主办的区别,再说,随便拿问题问部门同事、问省公司信息部的人,到最后发现那根本就是不足道的小问题、或者根本不算问题的问题,这样的次数多了,无益于自己的能力养成,更不利于自己的形象......虽然最后通常是要被指点,但是在自己排查问题的过程中,我更加清楚真正的问题在哪,能够做到深入思考,最后的收获是不言而喻的!
这次,又接到了货船险事业部 J 的提数需求:要提2013年和2014年一季度的保单主险费率清单。
这是一个新需求,通过问询,我知道了他们要的数据在系统中的位置(这样便于对比结果,还有找出对应的数据库表),明确了时间段和一些基本字段。最后重点问清的是:他们要的是全部保单的数据,还是剔除了预约协议(大保单)的数据,还是剔除了小保单的数据。回复是剔除了全部小保单的数据。(因为他们说小保单的费率不会超出大保单的费率,剔除了小保单不影响他们的统计分析)
如何去除清单中的小保单,这是我遇到的新问题,问了带我工作入门的Y姐,她说保单中间带E的就是小保单,于是我写了“proposalno[17]!='E' ”;Y姐还告诉我,对应保险责任表序号第一个的就是主险,其它是附加险,于是我写了“c.itemkindno ='1' ”。
根据这些条件,我写了第一个版本的语句如下:
select a.comcode,b.insuredname,a.ProposalNo,c.riskcode,a.StartDate,a.enddate,c.amount,c.Premium,c.currency,c.rate from prpcmain a,PrpCitemKind c,prpcinsured b
where (a.comcode[1,4]='4201' or a.comcode[1,6]='429004')
and a.classcode in ('08','09')
and a.underwriteflag in ('1','3')
and b.InsuredFlag[1]='1'
and a.proposalno =b.proposalno
and a.proposalno =c.proposalno
and c.itemkindno ='1' --取保险责任第一条,即主险代码
and a.proposalno[17]!='E' --去除大保单下的小保单
and (year(a.startdate) ='2013' or (year(a.startdate)= '2014' and month(a.startdate)<'4'))
查询结果近3万条。我随便抽了不同险种的几笔单子去系统中核查,发现有的是小保单!就是说以上语句没有把小保单去除干净!
分别拿了小保单和独立保单,对照主表查询,根据Y姐的指点,发现两者有个字段“policytype”不一致,该笔小保单的这个标志是“19”,于是我又加了一个筛选条件:and a.policytype!='19' 。再查,数据结果少了两千多条。再抽几笔保单进系统查,这下还是有问题!有几笔查到还是小保单!
再对照主表,发现未排除的小保单的policytype是22。既然如此,我把条件补成了and a.policytype not in ('19','22') 。根据提出来的结果,再拿几笔去核查,还是有小保单!
我感觉这筛除小保单的条件实在有问题,问了Y姐policytype对应的值分别有哪些,这些值对应了什么意思?Y姐说不知道......
没办法,总不能继续慢慢排查下去。我把如何排查小保单作为主要问题,咨询省公司技术支持W,还把已写的条件列上,问他这些条件写法是否正确、是否充分,问他policytype对应的值和相应的意思。W回复说也不知道这个字段的详细意思......继续问他要如何排除小保单,W说还没现成方案。
继续说明情况,追问他。他隔了一会回复到:
select a.proposalno from prpcmain a left join prpcmainsub b
on a.proposalno=b.proposalno
where a.riskcode[1]='Y' and b.proposalno is null 不是大保单下的小保单
这里给出了一个我没印象的表,采取的是另外的排查思路。我查数据结构文档,发现这个表有投保单号proposalno和主投保单号mainproposalno,这么说,主投保单号对应的是大保单,而投保单号对应的应该是小保单。把语句改造一下,做一个测试。(测语句是否正确、测结果是否一致、我喜欢各种测......):
select a.comcode,b.insuredname,a.ProposalNo,c.riskcode,a.StartDate,a.enddate,c.amount,c.Premium,c.currency,c.rate from prpcmain a,PrpCitemKind c,prpcinsured b,prpcmainsub d
where (a.comcode[1,4]='4201' or a.comcode[1,6]='429004')
and a.classcode in ('08','09')
and a.underwriteflag in ('1','3')
and b.InsuredFlag[1]='1'
and a.proposalno =b.proposalno
and a.proposalno =c.proposalno
and a.proposalno =d.proposalno --设为相等。查出那些是小保单的单子,再看是否正确
and c.itemkindno ='1'
--and a.proposalno[17]!='E' --原先的条件作为检验句,可以看它们的遗漏数据
--and a.policytype not in('22','19')
and c.amount != '0' --这句是新需求,要求把退保了的数据也筛掉
and (year(a.startdate) ='2013' or (year(a.startdate)= '2014' and month(a.startdate)<'4'))
通过以上方案,详细比对,我发现小保单的policytype分别还有01、20等值.....也就是说一开始用policytype不等于某个值的做法根本不全面,即使是按照已经提出来的policytype值全部排除,那还有可能有漏网之鱼......
在测试的过程中,我还发现大保单的policytype也有19、22这些值!这个值不因是大保单还是小保单而改变,是根据险种而改变的!这就说明前面的方案不仅删除了小保单,还把大保单也删掉了!更加确认了第一种思路的不可取。
基于测试摸索的结论,我写出了新的方案:
select a.comcode,b.insuredname,a.ProposalNo,c.riskcode,a.StartDate,a.enddate,c.amount,c.Premium,c.currency,c.rate from PrpCitemKind c,prpcinsured b,prpcmain a
left join prpcmainsub d
on a.proposalno=d.proposalno
where (a.comcode[1,4]='4201' or a.comcode[1,6]='429004')
and a.classcode in ('08','09')
and a.underwriteflag in ('1','3')
and b.InsuredFlag[1]='1'
and a.proposalno =b.proposalno
and a.proposalno =c.proposalno
and d.proposalno is null
and c.itemkindno ='1'
--and a.policytype not in('22','19') --检验句。不能加,因会删除大保单!
--and a.proposalno[17]='E' --检验句。测试无数据,说明不需要这条
and c.amount != '0'
and (year(a.startdate) ='2013' or (year(a.startdate)= '2014' and month(a.startdate)<'4'))
用以上方案提出2万7千多笔数据,检查了几笔,都没有问题,于是我满意地发给了事业部J。这是发给他的第二(还是第三?)个版本...>_<...
以上经历发生在一天的近12点到近5点之间(中间几乎没有并行其他事...),如果就这么结束了的话,这件事好像也没有能够激发我写作的念头,问题是它还没有完,又有新的问题!!
第二天,事业部 J 不知是怀疑数据不正确还是统计结果不满意,又找我提数,要把附加险的清单提给他。
我一开始毫不在意,把c.itemkindno ='1'改成c.itemkindno >'1',提出1400多笔数据就给了他。就在提数前,一点细致认真的习惯使我多加了几个字段,其中一个是c.itemkindno,这会便于查看同一笔单子的附加险。而就在把清单给了他之后,一个无意的浏览,我发现了一笔不和谐的保单,它的itemkindno 是3、4、5,没有2!
我单独去查这一笔单子,发现它在PrpCitemKind表里一共就只有3条数据,序号不仅没有2,连1也没有!这意味着我按照这个序号为1作为主险代码根本就不靠谱!而在业务系统中查,保险责任列表清清楚楚有1、2、3的排序,分别对应数据库提出的3、4、5!
我把发现的问题上升了一个高度,回到最初的需求再向自己提问:在哪个表(PrpCitemKind )有判断主险和附加险的标志,如何筛选主险和附加险?
自己先探寻了一番,没什么线索,然后再问带我入门的Y姐,她也表示摸不着门道......没办法,我确定自己没辙,就把这个问题描述一番,拿去和省公司技术部 W探讨。他迟迟没有回复。
我先把这个判断序号的限制条件去掉,把全部序号的数据都提出来差不多30000笔就发给了事业部J,告诉他序号为1的就是主险的,对于某些没有序号1的再区分判断。这番交涉不详说,颇有些无奈的味道。我就这样不厚道地把问题抛给了J...><...
省公司W 终于回复了:“数据字典 PrpDriskClause的ClauseAttribute条款属性:1:主险;2:附加险” 。换一个说法就是:另一个库里的一个表里有判断主险和附加险的字段。
W只有一句话,没有多说,我就先不问,自己再去测试一下。测试要解决的就是新的这个库表和原有语句的关联与整合问题。这里就不想多说过程了,只说结果就是:我用了一个第一眼看到的关键字段和排查了一段时间才确定的隐含条件,终于把新的表和原用到的表关联起来。测试语句如下:
select * from prpcitemkind b,outer hb4200dms3gdb:PrpDriskClause a --要用数据字典的这个表!
where a.clausecode =b.clausecode
and a.riskcode =b.riskcode --不加的话,有重复值!!看了好久才知道是它作怪...
and b.proposalno in ('TCBA201242010000000653')
稍稍松了一口气以后,我又进入测试中,这下也花费了一些时间,加了临时表才解决问题:
select a.comcode,b.insuredname,a.ProposalNo,c.riskcode,a.StartDate,a.enddate,c.amount,c.Premium,c.currency,c.rate,c.KindCode,c.kindname,c.itemkindno,c.clausecode from PrpCitemKind c,prpcinsured b,prpcmain a
left join prpcmainsub d
on a.proposalno=d.proposalno
where (a.comcode[1,4]='4201' or a.comcode[1,6]='429004')
and a.classcode in ('08','09')
and a.underwriteflag in ('1','3')
and b.InsuredFlag[1]='1'
and a.proposalno =b.proposalno
and a.proposalno =c.proposalno
and d.proposalno is null
and c.amount != '0'
and (year(a.startdate) ='2013' or (year(a.startdate)= '2014' and month(a.startdate)<'4'))
into temp tem_g with no log;
select f.ClauseAttribute,g.* from tem_g g,outer hb4200dms3gdb:PrpDriskClause f
where g.clausecode =f.clausecode
and g.riskcode =f.riskcode
-----------------------------------------------------------------------------------------------------------------------------------------------------------
终于又是一则工作上的经历,写在这里应该不会有多少读者——就算有,恐怕也不会有多少共鸣......
把自己的所做、所思、所悟写下来,想想好处总会是多于坏处的,至少上班的空闲时间没有浪费。
继续投入日常工作了......
20140417