最近项目上有让写视图,实现的功能是根据险种X编码X币种X公司类别分别显示当前年截止到今天的余额。
问题是,这些不同类别的业务不是每天都有收支,有的一天有好几笔。有的很久都没有。但是视图要提供的结果是需要显示出现过的所有类型的业务的余额展示。
--这段sql也比较正常,显示的就是普通的查询
create or replace view v_n_test_jine as -- 视图和查询语句没什么差别,怎么写都行
SELECT h.urancecode C_PROD_NO, --险种编码
b.accountcode C_SBJT_NO, --科目类型
f.code C_DPTACC_NO, --做账机构
w.name C_CUR_NO, --币种localcreditamountsum --本币贷方 localdebitamountsum, -- 本币借方
(case when b.accountcode in('6031') then sum(b.localcreditamountsum - b.localdebitamountsum) when b.accountcode in('6541','6542','6421','651101','651105') then sum(b.localdebitamountsum - b.localcreditamountsum) end ) as N_JINE,
--sum(b.localcreditamountsum - b.localdebitamountsum) N_AMT , --合计金额
substr(b.prepareddatev, 1, 10) T_DUE_TM, --凭证时间
--to_char(sysdate , 'yyyy-mm-dd') T_CRT_TM --生成时间
to_char(sysdate , 'yyyy-mm-dd hh24:mi:ss') T_CRT_TM --生成时间
from (select * from
(select
gl_detail.pk_voucher pk_voucher,
-- gl_detail.accountcode accountcode,
(case when substr(gl_detail.accountcode,0,4) = '6031' then '6031'
when substr(gl_detail.accountcode,0,4) = '6541' then '6541'
when substr(gl_detail.accountcode,0,4) = '6542' then '6542'
when substr(gl_detail.accountcode,0,4) = '6421' then '6421'
when substr(gl_detail.accountcode,0,6) = '651101' then '651101'
when substr(gl_detail.accountcode,0,6) = '651105' then '651105'
end
)as accountcode,
gl_detail.assid assid,
gl_detail.pk_currtype pk_currtype,
gl_detail.pk_accasoa pk_accasoa,
gl_detail.prepareddatev prepareddatev,
sum(gl_detail.debitamount) localdebitamountsum, -- 原币借方
sum(gl_detail.creditamount) localcreditamountsum --原币贷方
from gl_detail gl_detail
where gl_detail.dr = 0
-- and gl_detail.accountcode in ('6031%','6541%','6542%','6421%','651101%','651105%')
and gl_detail.accountcode like '6031%' or
gl_detail.accountcode like '6541%' or
gl_detail.accountcode like '6542%' or
gl_detail.accountcode like '6421%' or
gl_detail.accountcode like '651101%' or
gl_detail.accountcode like '651105%'
and gl_detail.adjustperiod <> to_char('12A')
group by
gl_detail.pk_voucher,
gl_detail.accountcode,
gl_detail.assid,
gl_detail.pk_currtype,
gl_detail.pk_accasoa,
gl_detail.prepareddatev)hh where substr(hh.prepareddatev, 1, 4) >= to_char(sysdate,'yyyy')
) b,
(select s.urancecode urancecode,g.assid assid from ins_bd_urancekind s,(select l.F18 F18, l.assid assid from gl_docfree1 l) g where s.pk_urancekind in g.F18) h,
(select p.name name,p.pk_currtype pk_currtype from bd_currtype p) w,
(select code,pk_org from org_orgs)f,
(select pk_org,pk_voucher from gl_voucher)v
where w.pk_currtype = b.pk_currtype
and h.assid = b.assid
and f.pk_org=v.pk_org
and b.pk_voucher = v.pk_voucher
group by h.urancecode,b.accountcode,w.name,substr(b.prepareddatev, 1, 10),f.code
order by T_DUE_TM desc
然后这样的话只是实现了不同类对同一天的余额实现了总和,于是乎怎么让每天不同种类的等于先前的所有的余额相加便成了问题。头疼一天没解决,好友给我发了这么段参考。
SQL如何实现:同列数据逐行相加?
该列第一行数据放在后面列第一行,第一行和第二行的和放后面列第二行,前三列的和放后面列的第三行,以此类推
例如:
A列 B列
11.25 11.25
25.25 36.5
50 86.5
60 146.5
要实现B列的数据
oracle实现的sql为:
SELECT t2.A, SUM(t1.A)
FROM (SELECT a, rownum RK from tab) t1
(SELECT a, rownum RK from tab) t2
WHERE t1.rk <= t2.rk
group by t2.a
ORDER BY T2.A
DB2实现的为:
SELECT t2.A, SUM(t1.A)
FROM (SELECT a, ROW_NUMBER() OVER(ORDER BY A) RK from tab) t1, (SELECT a, ROW_NUMBER() OVER(ORDER BY A) RK from tab) t2
WHERE t1.rk <= t2.rk
group by t2.a
ORDER BY T2.A
这说明了两个问题,一是我还是不太善用搜索,搜索的方向不太对。第二就是对sql的查询还是不够熟悉。
这段sql的主要思路就是,如何让一只鸡和自己亲嘴?答案就是克隆一个。
通过读这段sql并加以改造,
嵌套如下一个视图:
create or replace view web_Res_NC as
select t2.C_PROD_NO, --险种编码
t2.C_SBJT_NO, --科目类型
t2.C_DPTACC_NO, --做账机构
t2.C_CUR_NO, --币种
--t2.N_JINE, --合计金额
sum(t1.N_JINE) N_AMT, --累计合计金额
t2.T_DUE_TM, --业务时间
to_char(sysdate , 'yyyy-mm-dd') T_CRT_TM --生成时间
from
(select C_PROD_NO,
C_SBJT_NO,
C_DPTACC_NO, --做账机构
C_CUR_NO,
sum(N_JINE) N_JINE,
T_DUE_TM --业务时间
--T_CRT_TM, --生成时间
from v_n_test_jine group by C_PROD_NO,C_SBJT_NO,C_DPTACC_NO,C_CUR_NO,T_DUE_TM )t1,
(select C_PROD_NO,
C_SBJT_NO,
C_DPTACC_NO, --做账机构
C_CUR_NO,
sum(N_JINE) N_JINE,
T_DUE_TM --业务时间
--T_CRT_TM, --生成时间
from v_n_test_jine group by C_PROD_NO,C_SBJT_NO,C_DPTACC_NO,C_CUR_NO,T_DUE_TM )t2
where to_date(t1.T_DUE_TM||'00:00:01','yyyy-mm-dd hh24:mi:ss')<=to_date(t2.T_DUE_TM||'00:00:01','yyyy-mm-dd hh24:mi:ss')
and t1.C_PROD_NO=t2.C_PROD_NO
and t1.C_SBJT_NO=t2.C_SBJT_NO
and t1.C_CUR_NO=t2.C_CUR_NO
and t1.C_DPTACC_NO=t2.C_DPTACC_NO
group by t2.C_PROD_NO,
t2.C_SBJT_NO,
t2.C_DPTACC_NO,
t2.C_CUR_NO,
t2.T_DUE_TM
order by t2.T_DUE_TM desc
其中这里面关键的内容在于每条当天有数据的同一类型都可以有了到年初余额的相加,而每天的记录还都显示。
于是,实施让我实现的是,通过普通的select * from 视图名 where T_DUE_TM=”要查询的日期” ;
这个我想了半天实在搞不出来。让视图能查询随意日期,并且查出查询日前所有已有种类业务的余额和,只有从年初第一天的种。类和,只要第二天有新加的,就得都加上并显示在表中。实在做不到。
最终我只能给一段sql来实现这样的功能:
select a.C_PROD_NO,a.C_SBJT_NO,a.C_DPTACC_NO, a.C_CUR_NO, n.n_amt,n.t_due_tm, n.t_crt_tm from web_Res_NC n,
(select r.C_PROD_NO C_PROD_NO ,r.C_SBJT_NO C_SBJT_NO,r.C_DPTACC_NO C_DPTACC_NO,r.C_CUR_NO C_CUR_NO, max(t_due_tm) t_due_tm from web_Res_NC r
where substr(r.T_DUE_TM, 1, 10) <=to_char('2018-03-15') group by r.C_PROD_NO,r.C_SBJT_NO,r.C_DPTACC_NO,r.C_CUR_NO) a
where a.C_PROD_NO= n.C_PROD_NO and a.C_SBJT_NO=n.C_SBJT_NO and a.C_DPTACC_NO=n.C_DPTACC_NO and a.C_CUR_NO=n.C_CUR_NO and a.t_due_tm= n.t_due_tm
这段sql还有一个问题没有怎么解决,就是group by的时候,由于需要查询的表字段都需要group by ,余额这项不需要聚合的,只能就又嵌套了一遍,然后where写= 。经历尚浅,所以目前还不知道其他办法。
后来用函数写了段实现的该功能的sql,比这个简单了好多。但是,这段学习的经历还是很有用的。