Home » SQL & PL/SQL » SQL & PL/SQL » SQL or PL/SQL method required to fill up the values based on other table values (10.2.0.1.0)
SQL or PL/SQL method required to fill up the values based on other table values [message #633942] |
Sat, 28 February 2015 13:43 |
|
bluetooth420
Messages: 146 Registered: November 2011
|
Senior Member |
|
|
Hi.
Here are my two tables and its sample data
create table incoming (
sno number (4),
qty number(4),
unit number(4)
);
insert into incoming values (1, 4, 2);
insert into incoming values (2, 5, 3);
insert into incoming values (3, 8, 8);
insert into incoming values (4, 9, 9);
insert into incoming values (5, 9, 5);
insert into incoming values (6, 5, 6);
insert into incoming values (7, 9, 5);
insert into incoming values (8, 2, 4);
insert into incoming values (9, 6, 3);
insert into incoming values (10, 7, 2);
insert into incoming values (11, 2, 8);
insert into incoming values (12, 9, 9);
insert into incoming values (13, 5, 1);
insert into incoming values (14, 3, 7);
create table outgoing(
sno number (4),
oqty number(4),
Total_value number(4)
);
insert into outgoing values (1, 5, null);
insert into outgoing values (2, 8, null);
insert into outgoing values (3, 2, null);
insert into outgoing values (4, 9, null);
insert into outgoing values (5, 15, null);
insert into outgoing values (6, 4, null);
insert into outgoing values (7, 1, null);
insert into outgoing values (8, 5, null);
insert into outgoing values (9, 10, null);
insert into outgoing values (10, 6, null);
My requirement is to fill the total_value in FIFO order of incoming. i.e. (Using the incoming data on order of sno, fill total_value of outgoing)
IN other words my requirement is as follow
sno oqty total value
1 5 11
2 8 44
3 2 16
4 9 79
5 15 87
6 4 36
7 1 ..so on..
8 5 ..so on..
9 10 ..so on..
10 6 ..so on..
(--so on.. has to be computed as well)
and the method applied is as follow
sno oqty total value How computed Serial no used Left over
1 5 11 4x2 + 1 x3 1,2 4x3
2 8 44 4x3 + 4x8 2,3 4x8
3 2 16 2x8 3, 2x8
4 9 79 2x8 + 7x9 3,4 2x9
5 15 87 2x9 + 9x5 + 4x6 4,5, 6 1x6
6 4 36 1x6 + 5x5 6,7 4x5
7 1
8 5
9 10
10 6
My mind is puzzled to control the loops and even i am failed to start it.
Your guidance is needed to solve my problem.
Thanks.
(Note: actual data has hundred of rows. And sum(qty)>= sum(oqty) is always true)
[Edit MC: change quote tags to code ones]
[Updated on: Sat, 28 February 2015 13:54] by Moderator Report message to a moderator
|
|
|
|
Re: SQL or PL/SQL method required to fill up the values based on other table values [message #633949 is a reply to message #633948] |
Sat, 28 February 2015 16:12 |
|
Barbara Boehmer
Messages: 9090 Registered: November 2002 Location: California, USA
|
Senior Member |
|
|
The above is for a one-time update where the data is already in the outgoing table. If this is an ongoing system, then I would create a trigger on the outgoing table to update the values upon insert, as shown below.
SCOTT@orcl> -- incoming table:
SCOTT@orcl> create table incoming (
2 sno number (4),
3 qty number(4),
4 unit number(4)
5 );
Table created.
SCOTT@orcl> -- incoming data:
SCOTT@orcl> insert into incoming values (1, 4, 2);
1 row created.
SCOTT@orcl> insert into incoming values (2, 5, 3);
1 row created.
SCOTT@orcl> insert into incoming values (3, 8, 8);
1 row created.
SCOTT@orcl> insert into incoming values (4, 9, 9);
1 row created.
SCOTT@orcl> insert into incoming values (5, 9, 5);
1 row created.
SCOTT@orcl> insert into incoming values (6, 5, 6);
1 row created.
SCOTT@orcl> insert into incoming values (7, 9, 5);
1 row created.
SCOTT@orcl> insert into incoming values (8, 2, 4);
1 row created.
SCOTT@orcl> insert into incoming values (9, 6, 3);
1 row created.
SCOTT@orcl> insert into incoming values (10, 7, 2);
1 row created.
SCOTT@orcl> insert into incoming values (11, 2, 8);
1 row created.
SCOTT@orcl> insert into incoming values (12, 9, 9);
1 row created.
SCOTT@orcl> insert into incoming values (13, 5, 1);
1 row created.
SCOTT@orcl> insert into incoming values (14, 3, 7);
1 row created.
SCOTT@orcl> alter table incoming add (remaining number)
2 /
Table altered.
SCOTT@orcl> update incoming set remaining = qty
2 /
14 rows updated.
SCOTT@orcl> select * from incoming
2 /
SNO QTY UNIT REMAINING
---------- ---------- ---------- ----------
1 4 2 4
2 5 3 5
3 8 8 8
4 9 9 9
5 9 5 9
6 5 6 5
7 9 5 9
8 2 4 2
9 6 3 6
10 7 2 7
11 2 8 2
12 9 9 9
13 5 1 5
14 3 7 3
14 rows selected.
SCOTT@orcl> -- outgoing table:
SCOTT@orcl> create table outgoing(
2 sno number (4),
3 oqty number(4),
4 Total_value number(4)
5 );
Table created.
SCOTT@orcl> -- trigger:
SCOTT@orcl> create or replace trigger outgoing_bir
2 before insert on outgoing
3 for each row
4 declare
5 v_oqty number := :new.oqty;
6 v_total number := 0;
7 begin
8 while v_oqty > 0 loop
9 for i in
10 (select * from incoming where remaining > 0 order by sno)
11 loop
12 if v_oqty >= i.remaining then
13 v_total := v_total + (i.remaining * i.unit);
14 update incoming
15 set remaining = remaining - i.remaining
16 where sno = i.sno;
17 v_oqty := v_oqty - i.remaining;
18 else
19 v_total := v_total + (v_oqty * i.unit);
20 update incoming
21 set remaining = remaining - v_oqty
22 where sno = i.sno;
23 v_oqty := 0;
24 end if;
25 end loop;
26 end loop;
27 :new.total_value := v_total;
28 end outgoing_bir;
29 /
Trigger created.
SCOTT@orcl> show errors
No errors.
SCOTT@orcl> -- outgoing data:
SCOTT@orcl> insert into outgoing values (1, 5, null);
1 row created.
SCOTT@orcl> insert into outgoing values (2, 8, null);
1 row created.
SCOTT@orcl> insert into outgoing values (3, 2, null);
1 row created.
SCOTT@orcl> insert into outgoing values (4, 9, null);
1 row created.
SCOTT@orcl> insert into outgoing values (5, 15, null);
1 row created.
SCOTT@orcl> insert into outgoing values (6, 4, null);
1 row created.
SCOTT@orcl> insert into outgoing values (7, 1, null);
1 row created.
SCOTT@orcl> insert into outgoing values (8, 5, null);
1 row created.
SCOTT@orcl> insert into outgoing values (9, 10, null);
1 row created.
SCOTT@orcl> insert into outgoing values (10, 6, null);
1 row created.
SCOTT@orcl> commit;
Commit complete.
SCOTT@orcl> -- results:
SCOTT@orcl> select * from incoming
2 /
SNO QTY UNIT REMAINING
---------- ---------- ---------- ----------
1 4 2 0
2 5 3 0
3 8 8 0
4 9 9 0
5 9 5 0
6 5 6 0
7 9 5 0
8 2 4 0
9 6 3 0
10 7 2 0
11 2 8 1
12 9 9 9
13 5 1 5
14 3 7 3
14 rows selected.
SCOTT@orcl> select * from outgoing
2 /
SNO OQTY TOTAL_VALUE
---------- ---------- -----------
1 5 11
2 8 44
3 2 16
4 9 79
5 15 87
6 4 21
7 1 5
8 5 25
9 10 30
10 6 18
10 rows selected.
|
|
|
|
|
|
|
|
Re: SQL or PL/SQL method required to fill up the values based on other table values [message #633959 is a reply to message #633955] |
Sun, 01 March 2015 04:09 |
|
Barbara Boehmer
Messages: 9090 Registered: November 2002 Location: California, USA
|
Senior Member |
|
|
bluetooth420 wrote on Sat, 28 February 2015 23:35As per method in message in message #633948 , everything works fine.
But if i rerun the procedure for second time, the system hangs. why is it so? possible cause?
Try using a FOR LOOP instead of a CURSOR, adding ROWID, and making sure that you COMMIT afterwards, as shown below. Hopefully, that should eliminate potential problems with row locking and duplicates.
SCOTT@orcl12c> alter table incoming add (remaining number)
2 /
Table altered.
SCOTT@orcl12c> update incoming set remaining = qty
2 /
14 rows updated.
SCOTT@orcl12c> declare
2 v_oqty number := 0;
3 v_total number := 0;
4 begin
5 for o_rec in
6 (select rowid rid, outgoing.*
7 from outgoing
8 order by sno, rowid)
9 loop
10 v_oqty := o_rec.oqty;
11 v_total := 0;
12 while v_oqty > 0 loop
13 for i_rec in
14 (select rowid rid, incoming.* from incoming where remaining > 0 order by sno, rowid)
15 loop
16 if v_oqty >= i_rec.remaining then
17 v_total := v_total + (i_rec.remaining * i_rec.unit);
18 --
19 update incoming
20 set remaining = remaining - i_rec.remaining
21 where sno = i_rec.sno
22 and rowid = i_rec.rid;
23 --
24 v_oqty := v_oqty - i_rec.remaining;
25 else
26 v_total := v_total + (v_oqty * i_rec.unit);
27 --
28 update incoming
29 set remaining = remaining - v_oqty
30 where sno = i_rec.sno
31 and rowid = i_rec.rid;
32 --
33 v_oqty := 0;
34 end if;
35 end loop;
36 end loop;
37 --
38 update outgoing
39 set total_value = v_total
40 where sno = o_rec.sno
41 and rowid = o_rec.rid;
42 end loop;
43 end;
44 /
PL/SQL procedure successfully completed.
SCOTT@orcl12c> commit
2 /
Commit complete.
SCOTT@orcl12c> select * from incoming order by sno
2 /
SNO QTY UNIT REMAINING
---------- ---------- ---------- ----------
1 4 2 0
2 5 3 0
3 8 8 0
4 9 9 0
5 9 5 0
6 5 6 0
7 9 5 0
8 2 4 0
9 6 3 0
10 7 2 0
11 2 8 1
12 9 9 9
13 5 1 5
14 3 7 3
14 rows selected.
SCOTT@orcl12c> select * from outgoing order by sno
2 /
SNO OQTY TOTAL_VALUE
---------- ---------- -----------
1 5 11
2 8 44
3 2 16
4 9 79
5 15 87
6 4 21
7 1 5
8 5 25
9 10 30
10 6 18
10 rows selected.
|
|
|
|
Re: SQL or PL/SQL method required to fill up the values based on other table values [message #633961 is a reply to message #633960] |
Sun, 01 March 2015 04:24 |
|
Barbara Boehmer
Messages: 9090 Registered: November 2002 Location: California, USA
|
Senior Member |
|
|
The following revision should allow you to run it on a second data set where you run out of incoming qty.
SCOTT@orcl12c> alter table incoming add (remaining number)
2 /
Table altered.
SCOTT@orcl12c> update incoming set remaining = qty
2 /
14 rows updated.
SCOTT@orcl12c> declare
2 v_oqty number := 0;
3 v_total number := 0;
4 begin
5 for o_rec in
6 (select rowid rid, outgoing.*
7 from outgoing
8 order by sno, rowid)
9 loop
10 v_oqty := o_rec.oqty;
11 v_total := 0;
12 for i_rec in
13 (select rowid rid, incoming.* from incoming where remaining > 0 order by sno, rowid)
14 loop
15 if v_oqty >= i_rec.remaining then
16 v_total := v_total + (i_rec.remaining * i_rec.unit);
17 --
18 update incoming
19 set remaining = remaining - i_rec.remaining
20 where sno = i_rec.sno
21 and rowid = i_rec.rid;
22 --
23 v_oqty := v_oqty - i_rec.remaining;
24 else
25 v_total := v_total + (v_oqty * i_rec.unit);
26 --
27 update incoming
28 set remaining = remaining - v_oqty
29 where sno = i_rec.sno
30 and rowid = i_rec.rid;
31 --
32 v_oqty := 0;
33 end if;
34 if v_oqty = 0 then
35 exit;
36 end if;
37 end loop;
38 --
39 update outgoing
40 set total_value = v_total
41 where sno = o_rec.sno
42 and rowid = o_rec.rid;
43 end loop;
44 end;
45 /
PL/SQL procedure successfully completed.
SCOTT@orcl12c> commit
2 /
Commit complete.
SCOTT@orcl12c> select * from incoming order by sno
2 /
SNO QTY UNIT REMAINING
---------- ---------- ---------- ----------
1 4 2 0
2 5 3 0
3 8 8 0
4 9 9 0
5 9 5 0
6 5 6 0
7 9 5 0
8 2 4 0
9 6 3 0
10 7 2 0
11 2 8 1
12 9 9 9
13 5 1 5
14 3 7 3
14 rows selected.
SCOTT@orcl12c> select * from outgoing order by sno
2 /
SNO OQTY TOTAL_VALUE
---------- ---------- -----------
1 5 11
2 8 44
3 2 16
4 9 79
5 15 87
6 4 21
7 1 5
8 5 25
9 10 30
10 6 18
10 rows selected.
SCOTT@orcl12c> declare
2 v_oqty number := 0;
3 v_total number := 0;
4 begin
5 for o_rec in
6 (select rowid rid, outgoing.*
7 from outgoing
8 order by sno, rowid)
9 loop
10 v_oqty := o_rec.oqty;
11 v_total := 0;
12 for i_rec in
13 (select rowid rid, incoming.* from incoming where remaining > 0 order by sno, rowid)
14 loop
15 if v_oqty >= i_rec.remaining then
16 v_total := v_total + (i_rec.remaining * i_rec.unit);
17 --
18 update incoming
19 set remaining = remaining - i_rec.remaining
20 where sno = i_rec.sno
21 and rowid = i_rec.rid;
22 --
23 v_oqty := v_oqty - i_rec.remaining;
24 else
25 v_total := v_total + (v_oqty * i_rec.unit);
26 --
27 update incoming
28 set remaining = remaining - v_oqty
29 where sno = i_rec.sno
30 and rowid = i_rec.rid;
31 --
32 v_oqty := 0;
33 end if;
34 if v_oqty = 0 then
35 exit;
36 end if;
37 end loop;
38 --
39 update outgoing
40 set total_value = v_total
41 where sno = o_rec.sno
42 and rowid = o_rec.rid;
43 end loop;
44 end;
45 /
PL/SQL procedure successfully completed.
SCOTT@orcl12c> commit
2 /
Commit complete.
SCOTT@orcl12c> select * from incoming order by sno
2 /
SNO QTY UNIT REMAINING
---------- ---------- ---------- ----------
1 4 2 0
2 5 3 0
3 8 8 0
4 9 9 0
5 9 5 0
6 5 6 0
7 9 5 0
8 2 4 0
9 6 3 0
10 7 2 0
11 2 8 0
12 9 9 0
13 5 1 0
14 3 7 0
14 rows selected.
SCOTT@orcl12c> select * from outgoing order by sno
2 /
SNO OQTY TOTAL_VALUE
---------- ---------- -----------
1 5 44
2 8 48
3 2 2
4 9 21
5 15 0
6 4 0
7 1 0
8 5 0
9 10 0
10 6 0
10 rows selected.
|
|
|
|
Goto Forum:
Current Time: Thu Apr 25 04:11:57 CDT 2024
|