帐户表(accountentity) accountName代表:开户人 starttime:开户日期
id accountName accountstate accounttype starttime endtime account
1 test1 可用 活期 2008-3-1 2000
2 test2 可用 活期 2007-8-1 30000帐户详情表(accoundetailentity)
id time accountno money detailtype
1 2008-7-23 1 500 取
2 2008-7-31 1 300 取
3 2008-8-1 2 100 取
如何算出从2008-05-01 到 2008-08-01 的平均余额
也就是每天的余额相加除以2008-08-01到2008-05-01的日期差
id accountName accountstate accounttype starttime endtime account
1 test1 可用 活期 2008-3-1 2000
2 test2 可用 活期 2007-8-1 30000帐户详情表(accoundetailentity)
id time accountno money detailtype
1 2008-7-23 1 500 取
2 2008-7-31 1 300 取
3 2008-8-1 2 100 取
如何算出从2008-05-01 到 2008-08-01 的平均余额
也就是每天的余额相加除以2008-08-01到2008-05-01的日期差
解决方案 »
- ORA-12541错误总结
- oracle可以在查询中更新数据吗?
- 我要把oracle10g的数据库从旧电脑移植到新电脑
- oracle中将11,22,33,44,...,..,..,不定长度的字符串和中找到逗号(,),并截去出来。
- 提取话费清单时遇见的一个sql问题
- 问一个有关取最大值的函数
- powerdesigner创建的oracle数据库表为什么查询不了呢?
- 初学者向各位老师请教几个关于Oracle SQL*Plus问题!本人不甚感激,希望各位高人指点指点。有兴趣的进来看看!大家共同进步。谢谢!!
- Oracle备份文件导入的问题
- 如何配置Oracle的jdbc
- 如何在UNIX 导出Oracle的某一个表数据。
- sql navigator的执行动作在后台有没有相应的sql语句生成,如果有的话怎么查看?
SELECT A.ACCOUNTNAME,
A.STARTTIME,
(C.M + A.ACCOUNT) / (TO_DATE('2008-8-1', 'yyyy-mm-dd') - CASE
WHEN A.STARTTIME > TO_DATE('2008-5-1', 'yyyy-mm-dd') THEN
TRUNC(A.STARTTIME)
ELSE
TO_DATE('2008-5-1', 'yyyy-mm-dd')
END) AVG_MONEY
FROM ACCOUNTENTITY A,
(SELECT ACCOUNTNO, SUM(DECODE(DETAILTYPE, '取', - (MONEY), MONEY)) M
FROM ACCOUNDETAILENTITY B
WHERE B.TIME BETWEEN TO_DATE('2008-5-1', 'yyyy-mm-dd') AND
TO_DATE('2008-8-1', 'yyyy-mm-dd')
GROUP BY ACCOUNTNO) C
WHERE A.ID = C.ACCOUNTNO
AND A.STARTTIME < TO_DATE('2008-8-1', 'yyyy-mm-dd');
大体思路如下:
1、游标获取每个帐户的信息,利用游标循环处理每个帐户需求;
2、针对每一个帐户,利用循环获取每一次帐户变化情况就坚持的天数,相加求平均值;
3、应该会用到复杂的子查询,注意信息的匹配。也可以用分析函数,但还是要写存储过程,单个SQL语句貌似不能解决问题。
v_Num Number; ---时间段总计天数
v_Date Varchar2(20);--计数每一天日期值
v_Daynum Number(18, 2);--每天余额小计
v_Total Number(18, 2):=0;--时间段内余额总计
Begin
Select To_Date('2008-08-01', 'YYYY-MM-DD') -
To_Date('2008-05-01', 'YYYY-MM-DD')
Into v_Num
From Dual
For i In 0..v_Num
Loop
v_Date := To_Char(To_Date('2008-05-01', 'YYYY-MM-DD') + i, 'YYYY-MM-DD');
Select Sum(Account)
Into v_Daynum
From (
--当天新开户的
Select Id, Account
From Accountentity
Where Starttime = v_Date
Union
--当前s日期所有用户帐户余额
Select Id, Account
From (Select Id, Sum(Account) As Account
From (Select Id, Account
From Accountentity
Where Starttime <= v_Date
Union All
Select Accountno,
Decode(Detailtype, '取', -money, Money) As Money
From Accoundetailentity
Where Time <= v_Date)
Group By Id));
v_Total := v_Total+v_Daynum
End Loop
dbms_output.put_line(v_Total/v_Num);
End;
Declare
v_Num Number; ---时间段总计天数
v_Date Varchar2(20);--计数每一天日期值
v_Daynum Number(18, 2);--每天余额小计
v_Total Number(18, 2):=0;--时间段内余额总计
Begin
Select To_Date('2008-08-01', 'YYYY-MM-DD') -
To_Date('2008-05-01', 'YYYY-MM-DD')
Into v_Num
From Dual
For i In 0..v_Num
Loop
v_Date := To_Char(To_Date('2008-05-01', 'YYYY-MM-DD') + i, 'YYYY-MM-DD');
Select Sum(Account)
Into v_Daynum
From (
Select Id, Account
From (Select Id, Sum(Account) As Account
From (Select Id, Account
From Accountentity
Where Starttime <= v_Date
Union All
Select Accountno,
Decode(Detailtype, '取', -money, Money) As Money
From Accoundetailentity
Where Time <= v_Date)
Group By Id));
v_Total := v_Total+v_Daynum
End Loop
dbms_output.put_line(v_Total/v_Num);
End;
a1.accountname,
a1.accountstate,
a1.accounttype,
a1.starttime,
a1.endtime,
(a1.account +
sum(decode(a2.detailtype, '取', -a2.money, '存', a2.money, 0))) /
(case
when a1.starttime <= to_date('2008-05-01', 'yyyy-mm-dd') and
nvl(a1.endtime, trunc(sysdate) + 1) >=
to_date('2008-08-01', 'yyyy-mm-dd') then
to_date('2008-08-01', 'yyyy-mm-dd') -
to_date('2008-05-01', 'yyyy-mm-dd') + 1
when (a1.starttime between to_date('2008-05-01', 'yyyy-mm-dd') and
to_date('2008-08-01', 'yyyy-mm-dd')) and
nvl(a1.endtime, trunc(sysdate) + 1) >=
to_date('2008-08-01', 'yyyy-mm-dd') then
to_date('2008-08-01', 'yyyy-mm-dd') - a1.starttime + 1
when (a1.starttime between to_date('2008-05-01', 'yyyy-mm-dd') and
to_date('2008-08-01', 'yyyy-mm-dd')) and
(nvl(a1.endtime, trunc(sysdate) + 1) between
to_date('2008-05-01', 'yyyy-mm-dd') and
to_date('2008-08-01', 'yyyy-mm-dd')) then
a1.endtime - a1.starttime + 1
when a1.starttime > to_date('2008-08-01', 'yyyy-mm-dd') then
0
else
0
end) avg_amount
from a1, a2
where a1.id = a2.accountno(+)
and a1.starttime <= to_date('2008-08-01', 'yyyy-mm-dd')
and nvl(a2.time, to_date('2008-06-01', 'yyyy-mm-dd')) between
to_date('2008-05-01', 'yyyy-mm-dd') and
to_date('2008-08-01', 'yyyy-mm-dd')
group by a1.id,
a1.accountname,
a1.accountstate,
a1.accounttype,
a1.starttime,
a1.endtime,
a1.account
上面的写错了,修改下.
太复杂了!!SELECT z.accountno,z.accountname,z.STARTTIME,--COUNT(*),
SUM(fcm)/(TO_DATE('2008-8-1', 'yyyy-mm-dd') - CASE
WHEN z.STARTTIME > TO_DATE('2008-5-1', 'yyyy-mm-dd') THEN
TRUNC(z.STARTTIME)
ELSE
TO_DATE('2008-5-1', 'yyyy-mm-dd')
END+1) AVG_MONEY FROM (
WITH vv AS (SELECT TO_DATE('2008-5-1', 'yyyy-mm-dd') + ROWNUM - 1 VD
FROM DUAL
CONNECT BY ROWNUM <= TO_DATE('2008-8-1', 'yyyy-mm-dd') -
TO_DATE('2008-5-1', 'yyyy-mm-dd') + 1),
x AS (SELECT D.ACCOUNTNO, D.VD, D.RD, NVL(E.M, 0) M
FROM (SELECT B.ACCOUNTNO,
B.TIME,
DECODE(DETAILTYPE, '取', - (NVL(MONEY, 0)), NVL(MONEY, 0)) M
FROM ACCOUNDETAILENTITY B
WHERE B.TIME BETWEEN TO_DATE('2008-5-1', 'yyyy-mm-dd') AND
TO_DATE('2008-8-1', 'yyyy-mm-dd')) E,
(SELECT VD, ACCOUNTNO, ROWNUM RD
FROM VV,
(SELECT DISTINCT ACCOUNTNO
FROM ACCOUNDETAILENTITY
WHERE TIME BETWEEN TO_DATE('2008-5-1', 'yyyy-mm-dd') AND
TO_DATE('2008-8-1', 'yyyy-mm-dd'))) D
WHERE D.VD = E.TIME(+)
AND D.ACCOUNTNO = E.ACCOUNTNO(+)
ORDER BY D.VD, D.ACCOUNTNO),
y AS (SELECT ID, ACCOUNTNAME, STARTTIME, ACCOUNT, VD
FROM ACCOUNTENTITY A, VV AD
ORDER BY ID, VD)
SELECT X.ACCOUNTNO,
X.VD,
X.M,
Y.ACCOUNT,
FIRST_VALUE(Y.ACCOUNT) OVER(PARTITION BY X.ACCOUNTNO ORDER BY X.VD)
+ SUM(M) OVER(PARTITION BY X.ACCOUNTNO ORDER BY X.VD) FCM,
Y.ACCOUNTNAME,
Y.STARTTIME
FROM X, Y
WHERE X.VD = Y.VD
AND X.ACCOUNTNO = Y.ID) z
WHERE z.STARTTIME < TO_DATE('2008-8-1', 'yyyy-mm-dd')
GROUP BY z.accountno,z.accountname,z.STARTTIME
ORDER BY 1,2
;结果如下:
ACCOUNTNO ACCOUNTNAME STARTTIME AVG_MONEY
1 test1 2008-03-01 1939.78494623656
2 test2 2007-08-01 2998.9247311828