table personrisk
寿险表(保单号 险别 投保人ID 投保时间 保额)
policynolong riskcode personid createtime suminsured
ede123456 ede 1 2008-01-02 100000
ede123457 ede 2 2008-01-28 100000
ede123458 ede 5 2008-03-02 100000
table carrisk
车险表(保单号 险别 投保人ID 投保时间 保额)
policynolong riskcode personid createtime suminsured
edq123454 edq 4 2008-01-02 100000
edq123457 edq 2 2008-04-28 100000
edq123459 edq 6 2008-03-01 100000
table person
投保人表(投保人ID, 姓名 所属机构)
personid name organid
1 张三 3
2 王五 2
3 李四 1
4 赵六 2
5 田七 3
table organ
结构表(机构ID 机构名称)
orgid name
1 人保
2 太保
3 平安
4 太平
把上述数据按结构分月份统计各险别的保单笔数、保额收入,插入统计表中
下面给出统计表结构,以及一些假设数据
table stat
统计表(机构ID 月份 寿险 寿险保单笔数 车险 车险保单笔数)
orgid month personrisk personriskCount personriskSuminsured carrisk carriskCount carriskSuminsured
1 2008-2 ede 2 40000 edq 4 5000
1 2008-3 ede 0 0 edq 3 6000
2 2008-2 ede 3 5000 edq 0 0
从上面可以看出先按结构分组,然后按月份分组,再在同一条记录中计算各个险别的投保情况,没有投保的计为0。
请各位指点指点该如何来解决这个问题,sql,过程不限
[b]问题补充:[/b]
车险跟寿险不可能是同一张表,他们的属性不同的,这里只是抽出来他们相同的属性
[b]问题补充:[/b]
qamer 怎么做,你们还是写SQL 或者 过程吧,光说有啥意思
[b]问题补充:[/b]
哪里来的月份表?
[b]问题补充:[/b]
左连接结果不对呀。测试时车险75条记录,寿险97条记录,那么总单子顶多182单,左连接后居然有6843条记录几乎成了笛卡儿积了(75*97=7265)。
按照统计的要求这里车险和寿险应该是横向连接起来;而统计的单位和时间应该是纵向的;前者好比是x坐标轴,后者好比是y轴。
先来看看y 轴:
可以先找出统计的机构和月份
select o.orgid, to_char(pr.createtime, 'yyyymm') createtime
from personrisk pr, person p, org o
where pr.createid = p.personid AND p.orgid = o.orgid
union
select o.orgid, to_char(cr.createtime, 'yyyymm') createtime
from carrisk cr, person p, org o
where cr.createid = p.personid AND p.orgid = o.orgid
这样就保证了需要统计的所有机构和月份,兼顾车险和寿险
然后一上述结果为基础,横向连接,注意,这里不能用内连接,而要用外连接,内连接是筛选相同结果,那可能会是车险和寿险很多记录给漏掉了。
不妨先分别统计看看结果
寿险:
select o.orgid, to_char(pr.createtime, 'yyyymm') createtime, count(0) cnt, NVL(sum(pr.suminsured),0) suminsured, NVL(sum(pr.sumpremium),0) sumpremium
from personrisk pr, person p, org o
where pr.createid = p.personid AND p.orgid = o.orgid
group by o.orgid, to_char(pr.createtime, 'yyyymm')
order by o.orgid, createtime
车险:
select o.orgid, to_char(cr.createtime, 'yyyymm') createtime, count(0) cnt, NVL(sum(cr.suminsured),0) suminsured, NVL(sum(cr.sumpremium),0) sumpremium
from carrisk cr, person p, org o
where edq.createid = p.personid AND p.orgid = o.orgid
group by o.orgid, to_char(cr.createtime, 'yyyymm')
order by o.orgid, createtime
现在就可以把上面三个结果分别外连接起来:
这里简单的写一下,
select statunit.*, prisk.*, crisk.*
from ( select o.orgid, to_char(pr.createtime, 'yyyymm') createtime
from personrisk pr, person p, org o
where pr.createid = p.personid AND p.orgid = o.orgid
union
select o.orgid, to_char(cr.createtime, 'yyyymm') createtime
from carrisk cr, person p, org o
where cr.createid = p.personid AND p.orgid = o.orgid
) statunit, ( select o.orgid, to_char(pr.createtime, 'yyyymm') createtime, count(0) cnt, NVL(sum(pr.suminsured),0) suminsured, NVL(sum(pr.sumpremium),0) sumpremium
from personrisk pr, person p, org o
where pr.createid = p.personid AND p.orgid = o.orgid
group by o.orgid, to_char(pr.createtime, 'yyyymm')
order by o.orgid, createtime
) prisk, ( select o.orgid, to_char(cr.createtime, 'yyyymm') createtime, count(0) cnt, NVL(sum(cr.suminsured),0) suminsured, NVL(sum(cr.sumpremium),0) sumpremium
from carrisk cr, person p, org o
where edq.createid = p.personid AND p.orgid = o.orgid
group by o.orgid, to_char(cr.createtime, 'yyyymm')
order by o.orgid, createtime
) crisk
where statunit.orgid = prisk.orgid(+) and statunit.createtime = prisk.createtime(*) and statunit.orgid = crisk.orgid(+) and statunit.createtime = crisk.createtime(*)
上面的程序都经过测试了的。基本上满足问题的要求。个人感觉还有可优化的地方。统计在应用方面很广泛,特别是报表方面的处理。有空我会把这个问题写在我的博客里面。^_^个人感觉用过程处理会轻松许多,这里先到着再说吧。
其实你寿险,车险没必要弄两张表, 加个类别字段不就好了……
将车寿险合并,然后行转列
加一张月份表
可以用以下方式
[code="sql"]select
a.机构ID
, b.月份
, sum(nvl(c.保额, 0)) as 寿险
, count(decode(c.rowid, null, 0, 1)) as 寿险保单笔数
, sum(nvl(d.保额, 0)) as 车险
, count(decode(d.rowid, null, 0, 1)) as 车险保单笔数
from 投保人表 a
inner join 月份表 b on
1 = 1
left join 寿险表 c on
a.投保人ID = c.投保人ID
and c.投保时间 >= to_date(b.月份 || '01')
and c.投保时间 < add_months(to_date(b.月份 || '01'), 1)
left join 投保人表 d on
a.投保人ID = d.投保人ID
and d.投保时间 >= to_date(b.月份 || '01')
and d.投保时间 < add_months(to_date(b.月份 || '01'), 1)
where
(
c.rowid is not null
or d.rowid is not null
)
[/code]
需要注意的是,以上的sql中使用了左连接
不过,投保人表的数据很多的情况下,可能会有效率问题
当然,月份表中可以考虑添加“月初日”与“来月初日”
上面的sql文漏了一个group by条件
[code="sql"]
group by
a.机构ID
, b.月份
[/code]