超难sql语句,有人会写吗!

hc860102 2011-08-26 02:19:52
有表A,数据如下:
id accno date rn data1 data2 data3
111111111111111111 aaaaaa 2010-4-26 1 500 800
111111111111111111 bbbbbb 2010-5-7 2 1000 800
222222222222222222 dddddd 2010-1-14 1 1000 600
222222222222222222 gggggg 2010-2-7 2 2000 600
222222222222222222 hhhhhh 2010-2-24 3 3000 600
333333333333333333 nnnnnn 2010-3-14 1 500 3000
333333333333333333 mmmmmm 2010-4-11 2 1000 3000
333333333333333333 kkkkkk 2010-1-4 3 2000 3000
333333333333333333 tttttt 2010-5-14 4 4000 3000
333333333333333333 ffffff 2010-5-24 5 8000 3000
字段解释:
同一id下可以有多个accno
rn字段为对相同id按字段date时间排序
data1为日期对应金额
date2为该ID对应的可分摊金额
date3为每个accno实际得到的分摊金额

要求在对金额进行分摊时需要注意如下原则:
1、按时间顺序先后来分摊,即优先从日期小的开始分摊
2、每个accno对应的分摊金额不能大于data1
3、每个id对应的分摊金额汇总应该等于该ID对应的dat2
用sql语句分摊完金额,更新至data3字段,则结果应该为

id accno date rn data1 data2 data3
111111111111111111 aaaaaa 2010-4-26 1 500 800 500
111111111111111111 bbbbbb 2010-5-7 2 1000 800 300
222222222222222222 dddddd 2010-1-14 1 1000 600 600
222222222222222222 gggggg 2010-2-7 2 2000 600 0
222222222222222222 hhhhhh 2010-2-24 3 3000 600 0
333333333333333333 nnnnnn 2010-3-14 1 500 3000 500
333333333333333333 mmmmmm 2010-4-11 2 1000 3000 1000
333333333333333333 kkkkkk 2010-1-4 3 2000 3000 1500
333333333333333333 tttttt 2010-5-14 4 4000 3000 0
333333333333333333 ffffff 2010-5-24 5 8000 3000 0

请问我的sql语句应该怎么写!!!!!请大虾指教!!!!
...全文
185 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
billlyh 2011-08-26
  • 打赏
  • 举报
回复
declare
v_totall_m number; ----可分配金额
begin
for c1 in (select distinct id from t) loop
select data1 from t into v_totall_m;
for v_c in (select accno,data2 from t where t.id = c1.id order by date asc) loop
if v_totall_m - v_c.data2 > 0 then
update t set data3 = v_c.data2 where accno = v_c.accno and id = c1.id;
v_totall_m:= v_totall_m - v_c.data2;
else
update t set data3 = v_totall_m where accno = v_c.accno and id = c1.id;
goto l1;
end if;
end loop;
<<l1>>
commit;
end loop;
end;
桃花岛黄岛主 2011-08-26
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 hc860102 的回复:]
引用 15 楼 wang123kui 的回复:
引用 12 楼 hc860102 的回复:
引用 9 楼 wang123kui 的回复:
SQL code
declare
v_totall_m number; ----可分配金额
begin
for c1 in (select distinct id from t) loop
select data1 into v_totall_m……
[/Quote]

GOTO的作用是跳出第一个FOR循环 ,
没用过GOTO,可以到网上搜一下GOTO的用法,这个用法一般不建议使用,
会破坏程序结构的完整性.
hc860102 2011-08-26
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 wang123kui 的回复:]
引用 12 楼 hc860102 的回复:
引用 9 楼 wang123kui 的回复:
SQL code
declare
v_totall_m number; ----可分配金额
begin
for c1 in (select distinct id from t) loop
select data1 into v_totall_m from t where t.id = c1.i……
[/Quote]
恩,前面都看明白了 ,逻辑比较清晰。loop循环以前用过看的懂
但是goto l1 是什么意思,以前没用过goto。最后<<l1>> commit;这个<<l1>> 是起什么作用呢。
桃花岛黄岛主 2011-08-26
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 hc860102 的回复:]
引用 9 楼 wang123kui 的回复:
SQL code
declare
v_totall_m number; ----可分配金额
begin
for c1 in (select distinct id from t) loop
select data1 into v_totall_m from t where t.id = c1.id and rownum <2;
for v……
[/Quote]

逻辑并不复杂,静下心来你是能看明白的
lapheer 2011-08-26
  • 打赏
  • 举报
回复
大哥,这纯粹体力活啊!
nvhaixx 2011-08-26
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 nvhaixx 的回复:]
declare
n_money number; --可分配金额
s_accno char(6);
n_data1 number;
n_data2 number;
n_data3 number;
cursor c2(n_id number) is select accno,data1,data2 from a where id=n_id order by date;
begin
……
[/Quote]
纠正一下open c2(c1.id);
hc860102 2011-08-26
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 wang123kui 的回复:]
SQL code
declare
v_totall_m number; ----可分配金额
begin
for c1 in (select distinct id from t) loop
select data1 into v_totall_m from t where t.id = c1.id and rownum <2;
for v_c in (select a……
[/Quote]

黄岛主十分强大啊,能稍微注释一下吗?要求会不会有点过啊 -。-
nvhaixx 2011-08-26
  • 打赏
  • 举报
回复
declare
n_money number; --可分配金额
s_accno char(6);
n_data1 number;
n_data2 number;
n_data3 number;
cursor c2(n_id number) is select accno,data1,data2 from a where id=n_id order by date;
begin
for c1 in (select distinct id from a) loop
n_money:=0;
n_data3:=0;
open c2;
loop
fetch c2 into s_accno,nvl(n_data1,0),nvl(n_data2,0);
exit when c2%notfound;
if c2%rowcount=1 then
n_money:=n_data2-n_data1;
if n_money<0 then
n_data3:=n_data2;
else
n_data3:=n_data2-n_data1;
end if;
else
if n_money< 0 then
n_data3:=0;
else
if n_money<n_data1 then
n_data3:=n_money;
else
n_data3:=n_money-n_data1
end if;
end if ;
end if ;
update a set data3 = n_data3 where accno = s_accno and id = c1.id;
end loop;
close c2;
end loop;
commit;
end;
hc860102 2011-08-26
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 wang123kui 的回复:]
select data1 into v_totall_m from t where t.id = c1.id and rownum <2;


哎,仔细一看错误还真不少
[/Quote]

恩,应该是select data2 into v_totall_m from t where t.id = c1.id and rownum <2;
执行没报错了。我套到我的SQL里执行试试。非常感谢
桃花岛黄岛主 2011-08-26
  • 打赏
  • 举报
回复
declare
v_totall_m number; ----可分配金额
begin
for c1 in (select distinct id from t) loop
select data1 into v_totall_m from t where t.id = c1.id and rownum <2;
for v_c in (select accno,data1 from t where t.id = c1.id order by date asc) loop
if v_totall_m - v_c.data1 > 0 then
update t set data3 = v_c.data1 where accno = v_c.accno and id = c1.id;
v_totall_m:= v_totall_m - v_c.data1;
else
update t set data3 = v_totall_m where accno = v_c.accno and id = c1.id;
goto l1;
end if;
end loop;
<<l1>>
commit;
end loop;
end;


还是发个完整的吧
桃花岛黄岛主 2011-08-26
  • 打赏
  • 举报
回复
select data1 into v_totall_m from t where t.id = c1.id and rownum <2;


哎,仔细一看错误还真不少
桃花岛黄岛主 2011-08-26
  • 打赏
  • 举报
回复
select data1 into v_totall_m from t ;


哥哥,这样的错误你也看不出来啊
hc860102 2011-08-26
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 wang123kui 的回复:]
SQL code
declare
v_totall_m number; ----可分配金额
begin
for c1 in (select distinct id from t) loop
select data2 from t into v_totall_m;
for v_c in (select accno,data1 from t where t.id = c1……
[/Quote]

不行啊,报错了。黄岛主救命啊。
第5行 select data1 from t into v_totall_m; 的into报错:命令未正确结束。
桃花岛黄岛主 2011-08-26
  • 打赏
  • 举报
回复
declare
v_totall_m number; ----可分配金额
begin
for c1 in (select distinct id from t) loop
select data2 from t into v_totall_m;
for v_c in (select accno,data1 from t where t.id = c1.id order by date asc) loop
if v_totall_m - v_c.data1 > 0 then
update t set data3 = v_c.data1 where accno = v_c.accno and id = c1.id;
v_totall_m:= v_totall_m - v_c.data1;
else
update t set data3 = v_totall_m where accno = v_c.accno and id = c1.id;
goto l1;
end if;
end loop;
<<l1>>
commit;
end loop;
end;


上面好像列名写反了
桃花岛黄岛主 2011-08-26
  • 打赏
  • 举报
回复

declare
v_totall_m number; ----可分配金额
begin
for c1 in (select distinct id from t) loop
select data1 from t into v_totall_m;
for v_c in (select accno,data2 from t where t.id = c1.id order by date asc) loop
if v_totall_m - v_c.data2 > 0 then
update t set data3 = v_c.data2 where accno = v_c.accno and id = c1.id;
v_totall_m:= v_totall_m - v_c.data2;
else
update t set data3 = v_totall_m where accno = v_c.accno and id = c1.id;
goto l1;
end if;
end loop;
<<l1>>
commit;
end loop;
end;


为了赚点技术分不容易啊,哎
hc860102 2011-08-26
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 wang123kui 的回复:]
分太少了,不干
[/Quote]

咱就这么多分了~谁会写啊
yixilan 2011-08-26
  • 打赏
  • 举报
回复
楼主,不太明白“分摊”是什么意思。
不过,看数据好象明白了。
不过,真得挺复杂。
还是写存储过程来实现比较合适,在存储过程里用Cursor循环取出每个ID对应的记录。针对每条记录做计算。
桃花岛黄岛主 2011-08-26
  • 打赏
  • 举报
回复
分太少了,不干

17,086

社区成员

发帖
与我相关
我的任务
社区描述
Oracle开发相关技术讨论
社区管理员
  • 开发
  • Lucifer三思而后行
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧