Adding Bulk Collections into procedure in PLSQL - oracle

I have a procedure and it is used for inserting a table. It takes another table's datas and join them together then inserting new table.
In this procedure I want to use bulk collections for making these operations more faster. I am challenging in syntax and where to use these bulk collections.
Does anybody help or share ideas with me?
I am adding my database scripts below, thank you from now.
CREATE OR REPLACE procedure FCBSADM.extract_monthly_data(pid_billdate DATE) is
v_cnt NUMBER;
begin
execute immediate 'truncate table gpu';
v_cnt := 0;
FOR REC in (SELECT DISTINCT intl_prod_id
FROM apld_bill_rt abr,
acct_bill ab
WHERE abr.cdate > SYSDATE - 5
AND abr.CHRG_TP = 'INSTALLMENT'
AND abr.TAX_CATG_ID = 'NOTAX'
AND abr.acct_bill_id = ab.acct_bill_id
AND ab.bill_date = pid_billdate)
loop
INSERT INTO GPU
SELECT AB.ACCT_BILL_ID,
AB.BILL_NO,
AB.INV_ID,
AB.BILL_DATE,
ba2.bill_acct_id,
ba1.bill_acct_id parent_bill_acct_id,
AB.DUE_DATE,
PG.CMPG_ID,
ABR.NET_AMT,
AB.DUE_AMT,
P.PROD_NUM,
pds.DST_ID,
ABR.DESCR,
p.intl_prod_id
FROM apld_bill_rt abr,
acct_bill ab,
prod p,
FCBSADM.PROD_DST pds,
bill_acct_prod bap,
bill_acct ba1,
bill_acct ba2,
prod_cmpg pg
WHERE ab.intl_bill_acct_id = ba1.intl_bill_acct_id
AND AB.ACCT_BILL_ID = ABR.ACCT_BILL_ID
AND ba1.intl_bill_acct_id = ba2.parent_bill_acct_id
AND ba2.intl_bill_acct_id = bap.intl_bill_acct_id
AND bap.intl_prod_id = abr.intl_prod_id
AND ABR.CHRG_TP = 'INSTALLMENT'
AND abr.cdate > SYSDATE - 5
AND ABR.intl_prod_id = rec.intl_prod_id
AND bap.intl_prod_id = pds.intl_prod_id
AND bap.intl_prod_id = p.intl_prod_id
AND p.intl_prod_id = pg.intl_prod_id(+);
v_cnt := v_cnt + 1;
IF MOD (v_cnt, 1000) = 0
THEN
COMMIT;
END IF;
COMMIT;
end loop;
COMMIT;
end;
/
This is the last version of it. Errors are gone but no record is coming to GPU table and I am working on it.
create or replace procedure extract_monthly_data(pid_billdate DATE) is
v_cnt NUMBER;
TYPE prod_ids_t IS TABLE OF apld_bill_rt.intl_prod_id%TYPE INDEX BY PLS_INTEGER;
l_prod_ids prod_ids_t;
begin
execute immediate 'truncate table gpu';
v_cnt := 0;
SELECT DISTINCT abr.intl_prod_id, ab.bill_date BULK COLLECT INTO l_prod_ids
FROM apld_bill_rt abr,
acct_bill ab
WHERE abr.cdate > SYSDATE - 1000
AND abr.CHRG_TP = 'INSTALLMENT'
AND abr.TAX_CATG_ID = 'NOTAX'
AND abr.acct_bill_id = ab.acct_bill_id
ORDER BY bill_date;
FOR indx IN 1 .. l_prod_ids.COUNT
loop
INSERT INTO GPU
SELECT AB.ACCT_BILL_ID,
AB.BILL_NO,
AB.INV_ID,
AB.BILL_DATE,
ba2.bill_acct_id,
ba1.bill_acct_id parent_bill_acct_id,
AB.DUE_DATE,
PG.CMPG_ID,
ABR.NET_AMT,
AB.DUE_AMT,
P.PROD_NUM,
pds.DST_ID,
ABR.DESCR,
p.intl_prod_id
FROM apld_bill_rt abr
JOIN acct_bill ab ON AB.ACCT_BILL_ID = ABR.ACCT_BILL_ID
JOIN FCBSADM.PROD_DST pds ON
JOIN bill_acct_prod bap ON bap.intl_prod_id = abr.intl_prod_id
AND bap.intl_prod_id = pds.intl_prod_id
AND bap.intl_prod_id = p.intl_prod_id
JOIN prod p ON bap.intl_prod_id = p.intl_prod_id
JOIN bill_acct ba1 ON ab.intl_bill_acct_id = ba1.intl_bill_acct_id
JOIN bill_acct ba2 ON ba1.intl_bill_acct_id = ba2.parent_bill_acct_id
AND ba2.intl_bill_acct_id = bap.intl_bill_acct_id
LEFT OUTER JOIN prod_cmpg pg ON p.intl_prod_id = pg.intl_prod_id
WHERE ABR.CHRG_TP = 'INSTALLMENT'
AND abr.cdate > SYSDATE - 5
AND ABR.intl_prod_id =ANY (
SELECT intl_prod_id
FROM apld_bill_rt abr
JOIN acct_bill ab ON abr.acct_bill_id = ab.acct_bill_id
WHERE abr.cdate > SYSDATE - 1000
AND abr.CHRG_TP = 'INSTALLMENT'
AND abr.TAX_CATG_ID = 'NOTAX'
);
v_cnt := v_cnt + 1;
IF MOD (v_cnt, 1000) = 0
THEN
COMMIT;
END IF;
end loop;
COMMIT;
end;
This is the table that I want to insert into. The procedure compiled successfully but doesnt insert any record.
create table GPU
(
acct_bill_id NUMBER(16),
bill_no VARCHAR2(30 CHAR),
inv_id VARCHAR2(20 CHAR),
bill_date DATE,
bill_acct_id NUMBER(38),
parent_bill_acct_id NUMBER(38),
due_date DATE,
cmpg_id NUMBER,
net_amt NUMBER(16,2),
due_amt NUMBER(16,2),
prod_num VARCHAR2(32 CHAR),
dst_id NUMBER(22) not null,
descr VARCHAR2(100 CHAR),
intl_prod_id NUMBER(14) not null
);

You would not need any loop or bulk collect, but it is up to you. The reason is that you have all the values in the select distinct , and you are joining this dataset against the main query. It would be much better use a simple insert inside the procedure.
By the way, you should try to avoid this old syntax and start using normal SQL ANSI which is much easier to understand and maintain.
Option 1
Without cursor, nor bulk collect, just a simple insert select
CREATE OR REPLACE procedure FCBSADM.extract_monthly_data( pid_billdate DATE) is
begin
execute immediate 'truncate table gpu';
-- direct path is faster here, as you are truncating the table before
INSERT /*+append */ INTO GPU
with x as ( SELECT DISTINCT intl_prod_id
FROM apld_bill_rt abr,
acct_bill ab
WHERE abr.cdate > SYSDATE - 5
AND abr.CHRG_TP = 'INSTALLMENT'
AND abr.TAX_CATG_ID = 'NOTAX'
AND abr.acct_bill_id = ab.acct_bill_id
AND ab.bill_date = pid_billdate
)
SELECT AB.ACCT_BILL_ID,
AB.BILL_NO,
AB.INV_ID,
AB.BILL_DATE,
ba2.bill_acct_id,
ba1.bill_acct_id parent_bill_acct_id,
AB.DUE_DATE,
PG.CMPG_ID,
ABR.NET_AMT,
AB.DUE_AMT,
P.PROD_NUM,
pds.DST_ID,
ABR.DESCR,
p.intl_prod_id
FROM apld_bill_rt abr,
acct_bill ab,
prod p,
FCBSADM.PROD_DST pds,
bill_acct_prod bap,
bill_acct ba1,
bill_acct ba2,
prod_cmpg pg,
x
WHERE ab.intl_bill_acct_id = ba1.intl_bill_acct_id
AND AB.ACCT_BILL_ID = ABR.ACCT_BILL_ID
AND ba1.intl_bill_acct_id = ba2.parent_bill_acct_id
AND ba2.intl_bill_acct_id = bap.intl_bill_acct_id
AND bap.intl_prod_id = abr.intl_prod_id
AND ABR.CHRG_TP = 'INSTALLMENT'
AND abr.cdate > SYSDATE - 5
AND ABR.intl_prod_id = x.intl_prod_id
AND bap.intl_prod_id = pds.intl_prod_id
AND bap.intl_prod_id = p.intl_prod_id
AND p.intl_prod_id = pg.intl_prod_id(+);
COMMIT;
end;
Option 2
If you want to use bulk collect, which I don't recommend it here, one option might be. Check for any syntax error, as I did not have any way to replicate the code
CREATE OR REPLACE procedure FCBSADM.extract_monthly_data(pid_billdate DATE) is
v_cnt NUMBER;
TYPE prod_ids_t IS TABLE OF apld_bill_rt.intl_prod_id%TYPE INDEX BY PLS_INTEGER; -- whatever the table is
l_prod_ids prod_ids_t;
begin
execute immediate 'truncate table gpu';
v_cnt := 0;
SELECT DISTINCT intl_prod_id BULK COLLECT INTO l_prod_ids
FROM apld_bill_rt abr,
acct_bill ab
WHERE abr.cdate > SYSDATE - 5
AND abr.CHRG_TP = 'INSTALLMENT'
AND abr.TAX_CATG_ID = 'NOTAX'
AND abr.acct_bill_id = ab.acct_bill_id
AND ab.bill_date = pid_billdate);
FOR indx IN 1 .. l_prod_ids.COUNT
loop
INSERT INTO GPU
SELECT AB.ACCT_BILL_ID,
AB.BILL_NO,
AB.INV_ID,
AB.BILL_DATE,
ba2.bill_acct_id,
ba1.bill_acct_id parent_bill_acct_id,
AB.DUE_DATE,
PG.CMPG_ID,
ABR.NET_AMT,
AB.DUE_AMT,
P.PROD_NUM,
pds.DST_ID,
ABR.DESCR,
p.intl_prod_id
FROM apld_bill_rt abr,
acct_bill ab,
prod p,
FCBSADM.PROD_DST pds,
bill_acct_prod bap,
bill_acct ba1,
bill_acct ba2,
prod_cmpg pg
WHERE ab.intl_bill_acct_id = ba1.intl_bill_acct_id
AND AB.ACCT_BILL_ID = ABR.ACCT_BILL_ID
AND ba1.intl_bill_acct_id = ba2.parent_bill_acct_id
AND ba2.intl_bill_acct_id = bap.intl_bill_acct_id
AND bap.intl_prod_id = abr.intl_prod_id
AND ABR.CHRG_TP = 'INSTALLMENT'
AND abr.cdate > SYSDATE - 5
AND ABR.intl_prod_id = l_prod_ids(indx)
AND bap.intl_prod_id = pds.intl_prod_id
AND bap.intl_prod_id = p.intl_prod_id
AND p.intl_prod_id = pg.intl_prod_id(+);
v_cnt := v_cnt + 1;
IF MOD (v_cnt, 1000) = 0
THEN
COMMIT;
END IF;
end loop;
COMMIT;
end;

Related

Filtering data with previous month in plsql

I have a procedure which is used for extracting data and inserting them into one table. My problem is that I want to get previous months data by looking at bill_account_billcycle table's bill_date column. I have already seen so many examples about first and last day of previous month but I am looking for exactly the last month. Because bill date changes for ever customer in my case?
AND ab.bill_date = bab.bill_date;
so if I can look at previous month of bab.bill_date, I think it cant treat everyting. I am adding my procedure's scripts and one row from bill_account_cycle.bill_date for an example
I am open to any advices thank you from now.
create or replace procedure GPU_DATA_EXTRACTOR_TEST is
c_limit CONSTANT PLS_INTEGER DEFAULT 10000;
CURSOR c1 IS
SELECT DISTINCT intl_prod_id
FROM apld_bill_rt abr,
acct_bill ab,
bill_acct_billcycle bab
WHERE abr.CHRG_TP = 'INSTALLMENT'
AND abr.TAX_CATG_ID = 'NOTAX'
AND abr.acct_bill_id = ab.acct_bill_id
AND ab.bill_date = bab.bill_date;
TYPE prod_ids_t IS TABLE OF apld_bill_rt.intl_prod_id%TYPE INDEX BY PLS_INTEGER;
l_prod_ids prod_ids_t;
begin
execute immediate 'truncate table GPU_INV_TEST';
OPEN c1;
LOOP
FETCH c1 BULK COLLECT INTO l_prod_ids LIMIT c_limit;
EXIT WHEN l_prod_ids.COUNT = 0;
FORALL indx IN 1 .. l_prod_ids.COUNT
INSERT INTO GPU_INV_TEST
SELECT AB.ACCT_BILL_ID,
AB.BILL_NO,
AB.INV_ID,
AB.BILL_DATE,
ba2.bill_acct_id,
ba1.bill_acct_id parent_bill_acct_id,
AB.DUE_DATE,
PG.CMPG_ID,
ABR.NET_AMT,
AB.DUE_AMT,
P.PROD_NUM,
pds.DST_ID,
ABR.DESCR,
p.intl_prod_id
FROM apld_bill_rt abr,
acct_bill ab,
prod p,
FCBSADM.PROD_DST pds,
bill_acct_prod bap,
bill_acct ba1,
bill_acct ba2,
prod_cmpg pg
WHERE ab.intl_bill_acct_id = ba1.intl_bill_acct_id
AND AB.ACCT_BILL_ID = ABR.ACCT_BILL_ID
AND ba1.intl_bill_acct_id = ba2.parent_bill_acct_id
AND ba2.intl_bill_acct_id = bap.intl_bill_acct_id
AND bap.intl_prod_id = abr.intl_prod_id
AND ABR.CHRG_TP = 'INSTALLMENT'
AND bap.intl_prod_id = pds.intl_prod_id
AND bap.intl_prod_id = p.intl_prod_id
AND p.intl_prod_id = pg.intl_prod_id(+)
AND ABR.intl_prod_id = l_prod_ids(indx)
UNION
SELECT AB.ACCT_BILL_ID,
AB.BILL_NO,
AB.INV_ID,
AB.BILL_DATE,
ba1.bill_acct_id,
ba1.bill_acct_id parent_bill_acct_id,
AB.DUE_DATE,
PG.CMPG_ID,
ABR.NET_AMT,
AB.DUE_AMT,
P.PROD_NUM,
pds.DST_ID,
ABR.DESCR,
p.intl_prod_id
FROM apld_bill_rt abr,
acct_bill ab,
prod p,
FCBSADM.PROD_DST pds,
bill_acct_prod bap,
bill_acct ba1,
prod_cmpg pg
WHERE ab.intl_bill_acct_id = ba1.intl_bill_acct_id
AND AB.ACCT_BILL_ID = ABR.ACCT_BILL_ID
--AND ba1.intl_bill_acct_id = ba2.parent_bill_acct_id
AND ba1.intl_bill_acct_id = bap.intl_bill_acct_id
AND bap.intl_prod_id = abr.intl_prod_id
AND ABR.CHRG_TP = 'INSTALLMENT'
AND bap.intl_prod_id = pds.intl_prod_id
AND bap.intl_prod_id = p.intl_prod_id
AND p.intl_prod_id = pg.intl_prod_id(+)
AND ABR.intl_prod_id = l_prod_ids(indx);
COMMIT;
END LOOP;
CLOSE c1;
end;
I am looking for exactly the last month
If "last month" is "previous month", then you'd use values returned by
SQL> alter session set nls_date_format = 'dd.mm.yyyy';
Session altered.
SQL> select trunc(add_months(sysdate, -1), 'mm') date_from,
2 trunc(sysdate, 'mm') - 1 as date_to
3 from dual
4 /
DATE_FROM DATE_TO
---------- ----------
01.09.2021 30.09.2021
SQL>
and your query might look like
AND ab.bill_date BETWEEN trunc(add_months(sysdate, -1), 'mm')
AND trunc(sysdate, 'mm') - 1
AND ab.bill_date = bab.bill_date

LIMIT clause usage in PLSQL

I have a procedure which is used for extracting data and then inserting them. My problem is that I am using BULK COLLECTION. My goal is that I want to every time extract for example 10,000 data then insert these 10,000 records. But in my script I can limit it with that value but it doesn't insert more. For instance I have 6 records and I used 4 with LIMIT clause. What I want is the procedure should first insert 4 record then extract remaining 2 records for example.
I have I can describe issue briefly. I am open to any fix advices in my scripts. Thank you from now.
I solved my problem added new version of script below, thank you everyone
create or replace procedure GPU_DATA_EXTRACTOR_TEST(pid_billdate DATE) is
v_cnt NUMBER;
c_limit CONSTANT PLS_INTEGER DEFAULT 4;
CURSOR c1 IS
SELECT DISTINCT intl_prod_id
FROM apld_bill_rt abr,
acct_bill ab
WHERE abr.CHRG_TP = 'INSTALLMENT'
AND abr.TAX_CATG_ID = 'NOTAX'
AND abr.acct_bill_id = ab.acct_bill_id
AND ab.bill_date = pid_billdate;
TYPE prod_ids_t IS TABLE OF apld_bill_rt.intl_prod_id%TYPE INDEX BY PLS_INTEGER;
l_prod_ids prod_ids_t;
begin
execute immediate 'truncate table GPU_INV_TEST';
v_cnt := 0;
OPEN c1;
LOOP
FETCH c1 BULK COLLECT INTO l_prod_ids LIMIT c_limit;
EXIT WHEN l_prod_ids.COUNT = 0;
FOR indx IN 1 .. l_prod_ids.COUNT
loop
INSERT INTO GPU_INV_TEST
SELECT AB.ACCT_BILL_ID,
AB.BILL_NO,
AB.INV_ID,
AB.BILL_DATE,
ba2.bill_acct_id,
ba1.bill_acct_id parent_bill_acct_id,
AB.DUE_DATE,
PG.CMPG_ID,
ABR.NET_AMT,
AB.DUE_AMT,
P.PROD_NUM,
pds.DST_ID,
ABR.DESCR,
p.intl_prod_id
FROM apld_bill_rt abr,
acct_bill ab,
prod p,
FCBSADM.PROD_DST pds,
bill_acct_prod bap,
bill_acct ba1,
bill_acct ba2,
prod_cmpg pg
WHERE ab.intl_bill_acct_id = ba1.intl_bill_acct_id
AND AB.ACCT_BILL_ID = ABR.ACCT_BILL_ID
AND ba1.intl_bill_acct_id = ba2.parent_bill_acct_id
AND ba2.intl_bill_acct_id = bap.intl_bill_acct_id
AND bap.intl_prod_id = abr.intl_prod_id
AND ABR.CHRG_TP = 'INSTALLMENT'
AND bap.intl_prod_id = pds.intl_prod_id
AND bap.intl_prod_id = p.intl_prod_id
AND p.intl_prod_id = pg.intl_prod_id(+)
AND ABR.intl_prod_id = l_prod_ids(indx)
UNION
SELECT AB.ACCT_BILL_ID,
AB.BILL_NO,
AB.INV_ID,
AB.BILL_DATE,
ba1.bill_acct_id,
ba1.bill_acct_id parent_bill_acct_id,
AB.DUE_DATE,
PG.CMPG_ID,
ABR.NET_AMT,
AB.DUE_AMT,
P.PROD_NUM,
pds.DST_ID,
ABR.DESCR,
p.intl_prod_id
FROM apld_bill_rt abr,
acct_bill ab,
prod p,
FCBSADM.PROD_DST pds,
bill_acct_prod bap,
bill_acct ba1,
prod_cmpg pg
WHERE ab.intl_bill_acct_id = ba1.intl_bill_acct_id
AND AB.ACCT_BILL_ID = ABR.ACCT_BILL_ID
--AND ba1.intl_bill_acct_id = ba2.parent_bill_acct_id
AND ba1.intl_bill_acct_id = bap.intl_bill_acct_id
AND bap.intl_prod_id = abr.intl_prod_id
AND ABR.CHRG_TP = 'INSTALLMENT'
AND bap.intl_prod_id = pds.intl_prod_id
AND bap.intl_prod_id = p.intl_prod_id
AND p.intl_prod_id = pg.intl_prod_id(+)
AND ABR.intl_prod_id = l_prod_ids(indx);
v_cnt := v_cnt + 1;
IF MOD (v_cnt, 4) = 0
THEN
COMMIT;
END IF;
end loop;
COMMIT;
END LOOP;
CLOSE c1;
end;
You need a LOOP in order to fetch multiple subsets of records. Example snippet:
...
loop
FETCH c1 BULK COLLECT INTO l_prod_ids LIMIT c_limit;
exit when l_prod_ids.count = 0;
FOR indx IN 1 .. l_prod_ids.COUNT
...
end loop;
CLOSE c1;
...
Incidentally, executing thousands of individual INSERT statements is a recipe for poor performance. You should use the FORALL syntax (which is not a loop) to execute a set-based insert operation driving from your collection. Find out more.
You should also give consideration as to whether you ought to be using a collection at all, when you could just use a pure SQL INSERT INTO ... SELECT ... FROM statement. That would perform even better than a FORALL operation.

Convert SQL Server CTE into Oracle CTE

Here is the SQL Server CTE, trying to convert to Oracle CTE or regular oracle query..
;with cte as
(Select AC, M, Y, D, E, F, CD
from tblA
WHere
(Y = YEAR(GETDATE()) and M = Month(dateadd(month, -1, GETDATE())))
),
cte2 as
(Select A.AC,Max(A.Y)as Y, Max(A.M) as M, Max(A.CD) as CD
from tbl A
Inner join cte B on B.AC = A.AC
WHere A.CD is Not Null and B.CD is Null
Group by A.AC)
, cte3 as
(Select C.AC, C.Y, C.M, C.D, C.E, C.F, C.CD
from tblA C
Inner join cte2 D on C.AC = D.AC and C.Y= D.Y and C.M = D.M and
D.CD = C.CD
)
select * from cte
union
select * from cte3;
Assuming you didn't have the m and y columns reversed on purpose in your cte/cte3 select lists, I think you could rewrite your query as:
with cte1 as (select a.ac,
a.m,
a.y,
a.d,
a.e,
a.f,
a.cd,
max(case when a.cd is not null and b.cd is not null then a.y end) over (partition by a.ac) max_y,
max(case when a.cd is not null and b.cd is not null then a.m end) over (partition by a.ac) max_m,
max(case when a.cd is not null and b.cd is not null then a.cd end) over (partition by a.ac) max_cd
from tbla a
left outer join tblb b on (a.ac = b.ac))
select ac,
m,
y,
d,
e,
f,
cd
from cte1
where (y = to_char(sysdate, 'yyyy')
and m = to_char(add_months(sysdate, -1), 'mm'))
or (y = max_y
and m = max_m
and cd = max_cd);
You haven't provided any sample data, so I can't test, but it would be worth converting the date functions to their SQL Server equivalents and testing to make sure the data returned is the same.
This way, you're not querying the same table 3 times, which should improve the performance some.

Delphi time graph splitting algorithm

I have 3 records in ClientDataSet with structure:
Num: integer; Start: TTime; End: TTime;
1; 9:00; 10:00
2; 9:30; 10:00
3; 9:40; 10:20
I have to get those records to other ClientDataSet like this:
1; 9:00; 9:30
2: 9:30; 9:40
3; 9:40; 10:00
4; 10:00; 10:20
use TList<TTime>, populate it with both columns, sort it, then iterate through the list skipping duplicates. Like this.
var l: TList<TTime>; t1, t2: TTime; id2: cardinal;
begin
l := TList<TTime>.Create;
try
cds1.First;
while not cds1.Eof do begin
l.Add( Frac(cds1.Fields[1].AsDateTime) );
l.Add( Frac(cds1.Fields[2].AsDateTime) );
cds1.Next;
end;
l.Sort;
cds2.Clear;
if l.Count <= 0 then exit;
t1 := l[0]; id2 := 0;
for t2 in l do begin
if t1 > t2 then raise Exception.create ('Sort silently failed!') else
if t1 < t2 then begin
Inc(id2);
cds2.AppendRecord([ id2, t1, t2 ]);
t1 := t2;
end;
end;
finally
l.Free;
end;
end;

convert rows to columns in oracle [duplicate]

I have folowing Dataout put from my query
**Date** **HIGH** **LOW** **IMAGE** **TYPE**
1/28/2012 69 42 1.jpg SUN
1/29/2012 70 42 2.jpg MSUN
I want to Convert this Output into
**1/28/2012** **1/29/2012**
1.jpg 2.jpg
Sun MSUN
69 72
42 42
Here is My query
SELECT
W_DATE,HIGH, LOW,
W_TYPE, IMAGE
FROM WEATHER
ORDER BY W_DATE ASC
And Also I have multiple dates in rows i want to display only 4 dates and they should change when system date is chanaged
About all the possibilities how get from rows to columns in oracle you can read up here:
http://www.dba-oracle.com/t_converting_rows_columns.htm
I don't see a straight forward solution for that from database point of view - would suggest to do the formatting on application side, otherwise it could look as lame as this:
SELECT
to_char(w1.w_Date,'MM/DD/YYYY'), to_char(w2.w_Date,'MM/DD/YYYY'),
to_char(w3.w_Date,'MM/DD/YYYY'), to_char(w4.w_Date,'MM/DD/YYYY')
FROM
(select * from weather where w_date = trunc(sysdate)) w1,
(select * from weather where w_date = trunc(sysdate) + 1) w2,
(select * from weather where w_date = trunc(sysdate) + 2) w3,
(select * from weather where w_date = trunc(sysdate) + 3) w4
UNION ALL
SELECT
w1.image, w2.image, w3.image , w4.image
FROM
(select * from weather where w_date = trunc(sysdate)) w1,
(select * from weather where w_date = trunc(sysdate) + 1) w2,
(select * from weather where w_date = trunc(sysdate) + 2) w3,
(select * from weather where w_date = trunc(sysdate) + 3) w4
UNION ALL
SELECT
w1.w_type, w2.w_type, w3.w_type , w4.w_type
FROM
(select * from weather where w_date = trunc(sysdate)) w1,
(select * from weather where w_date = trunc(sysdate) + 1) w2,
(select * from weather where w_date = trunc(sysdate) + 2) w3,
(select * from weather where w_date = trunc(sysdate) + 3) w4
UNION ALL
SELECT
to_char(w1.high), to_char(w2.high), to_char(w3.high) , to_char(w4.high)
FROM
(select * from weather where w_date = trunc(sysdate)) w1,
(select * from weather where w_date = trunc(sysdate) + 1) w2,
(select * from weather where w_date = trunc(sysdate) + 2) w3,
(select * from weather where w_date = trunc(sysdate) + 3) w4
UNION ALL
SELECT
to_char(w1.low), to_char(w2.low), to_char(w3.low) , to_char(w4.low)
FROM
(select * from weather where w_date = trunc(sysdate)) w1,
(select * from weather where w_date = trunc(sysdate) + 1) w2,
(select * from weather where w_date = trunc(sysdate) + 2) w3,
(select * from weather where w_date = trunc(sysdate) + 3) w4;
/

Resources