Cell assignments in Model clause
Hi,
I have a table TEST_DATA with YEAR,FIELD,VALUE as columns.
The VALUE1 , VALUE2, VALUE 3 columns are determined based on the field values. If the data is as follows
YEAR FIELD VALUE
2010 1 11111
2010 2 22222
2010 3 33333
Can I get the output as follows using model clause.
YEAR VALUE1 VALUE2 VALUE3
2010 11111 222222 333333
2009 23243 533635 343434
2008 34343 364653 343434
2007 34345 789879 343434
I don't want to use pivot as I have to perform some computations on the above value columns. So I tried the following query using model clause
and value1,value2,value3 are coming in 3 different rows.
How do I write cell assignments to get the value 1,value 2,value 3 in the same row?
SELECT YEAR, VALUE 1,VALUE 2, VALUE 3
FROM TEST_FIN_DATA
MODEL
RETURN UPDATED ROWS
MAIN simple
PARTITION BY (YEAR)
DIMENSION BY (FIELD)
MEASURES (VALUE VALUE1, VALUE VALUE2, VALUE VALUE3 )
RULES
(value1['1'] = value1['1'] ,
value[('2'] = value['2'],
value['3'] = value['3']);
with data as (
select 2010 y, 1 f, 11111 v from dual union all
select 2010, 2, 222222 from dual union all
select 2010, 3, 333333 from dual union all
select 2009, 1, 111111 from dual union all
select 2009, 2, 222222 from dual union all
select 2009, 3, 333333 from dual
select y, v1, v2, v3 from
data
model
return updated rows
partition by (y)
dimension by (f)
measures (v, 0 v1, 0 v2, 0 v3)
rules(
v1[0]=v[1]
,v2[0]=v[2]
,v3[0]=v[3]
order by y desc
Y;V1;V2;V3
2010;11111;222222;333333
2009;111111;222222;333333compare to the query without return updated rows.
Trick is v?[0] creates a new (PIVOT-)row for every partition.
regards
Edited by: chris227 on 27.06.2012 06:15
Similar Messages
-
Avoiding null and duplicate values using model clause
Hi,
I am trying to use model clause to get comma seperated list of data : following is the scenario:
testuser>select * from test1;
ID VALUE
1 Value1
2 Value2
3 Value3
4 Value4
5 Value4
6
7 value5
8
8 rows selected.
the query I have is:
testuser>with src as (
2 select distinct id,value
3 from test1
4 ),
5 t as (
6 select distinct substr(value,2) value
7 from src
8 model
9 ignore nav
10 dimension by (id)
11 measures (cast(value as varchar2(100)) value)
12 rules
13 (
14 value[any] order by id =
15 value[cv()-1] || ',' || value[cv()]
16 )
17 )
18 select max(value) oneline
19 from t;
ONELINE
Value1,Value2,Value3,Value4,Value4,,value5,
what I find is that this query has duplicate value and null (',,') coming in as data has null and duplicate value. Is there a way i can avoid the null and the duplicate values in the query output?
thanks,
Edited by: orausern on Feb 19, 2010 5:05 AMHi,
Try this code.
with
t as ( select substr(value,2)value,ind
from test1
model
ignore nav
dimension by (id)
measures (cast(value as varchar2(100)) value, 0 ind)
rules
( ind[any]= instr(value[cv()-1],value[cv()]),
value[any] order by id = value[cv()-1] || CASE WHEN value[cv()] IS NOT NULL
and ind[cv()]=0 THEN ',' || value[cv()] END
select max(value) oneline
from t;
SQL> select * from test1;
ID VALUE
1 Value1
2 Value2
3 Value3
4 Value4
5 Value4
6
7 value5
8
8 ligne(s) sélectionnée(s).
SQL> with
2 t as ( select substr(value,2)value,ind
3 from test1
4 model
5 ignore nav
6 dimension by (id)
7 measures (cast(value as varchar2(100)) value, 0 ind)
8 rules
9 ( ind[any]= instr(value[cv()-1],value[cv()]),
10 value[any] order by id = value[cv()-1] || CASE WHEN value[cv()] IS NOT NULL
11 and ind[cv()]=0 THEN ',' || value[cv()] END
12 )
13 )
14 select max(value) oneline
15 from t;
ONELINE
Value1,Value2,Value3,Value4,value5
SQL> -
Hi Gurus,
Can someone please help me out.
I've a below tables.
1) tbl_link --> this table contains information at profile level
2) tbl_summary --> this table contains summary at parent profile level derived from tbl_link table
One parent profile contains multiple child profiles and each child profile links to a code (which is B, W, G or P) and the code is linked to a category (i.e. ONL and OFL). In this case code B is linked to category 'ONL' and codes W,G,P linked to OFL category.
ONL category needs 100 points. If it don't have enough points then i need to borrow from OFL category which i'm doing and populating into tbl_summary table at parent profile level.
Now i need to insert data into tbl_link table at profile level with howmany points used, expired based on tbl_summary table. Rule is at the end of month if we add points for each profile in tbl_link table it should come as 0.
with
tbl_SUMMARY as
select 1 as ppid,'ONL' as catgcode, 53 as earned_points,47 BORROWED_POINTS,100 CERT_POINTS,0 DISCARD_POINTS,100 used from dual
union
select 1 as ppid,'OFL' as catgcode, 223 as earned_points,0 BORROWED_POINTS,176 CERT_POINTS,76 DISCARD_POINTS,100 used from dual
union
select 2 as ppid,'ONL' as catgcode, 39 as earned_points,61 BORROWED_POINTS,100 CERT_POINTS,0 DISCARD_POINTS,100 used from dual
union
select 2 as ppid,'OFL' as catgcode, 90 as earned_points,0 BORROWED_POINTS,29 CERT_POINTS,29 DISCARD_POINTS,100 used from dual
union
select 3 as ppid,'ONL' as catgcode, 109 as earned_points,0 BORROWED_POINTS,109 CERT_POINTS,9 DISCARD_POINTS,100 used from dual
union
select 3 as ppid,'OFL' as catgcode, 223 as earned_points,0 BORROWED_POINTS,223 CERT_POINTS,23 DISCARD_POINTS,200 used from dual
union
select 4 as ppid,'ONL' as catgcode, 109 as earned_points,0 BORROWED_POINTS,109 CERT_POINTS,9 DISCARD_POINTS,100 used from dual
union
select 4 as ppid,'OFL' as catgcode, 169 as earned_points,0 BORROWED_POINTS,169 CERT_POINTS,69 DISCARD_POINTS,100 used from dual
tbl_link as
select 1 as ppid,1 as pid, 'B' as code,'ONL' as catgcode, 53 as earned_points from dual
union
select 1 as ppid,12 as pid, 'W' as code,'OFL' as catgcode, 26 as earned_points from dual
union
select 1 as ppid,13 as pid, 'G' as code,'OFL' as catgcode, 87 as earned_points from dual
union
select 1 as ppid,14 as pid, 'P' as code,'OFL' as catgcode, 110 as earned_points from dual
union
select 2 as ppid,2 as pid, 'B' as code,'ONL' as catgcode, 39 as earned_points from dual
union
select 2 as ppid,22 as pid, 'W' ,'OFL' as catgcode, 30 as earned_points from dual
union
select 2 as ppid,23 as pid, 'G' ,'OFL' as catgcode, 29 as earned_points from dual
union
select 2 as ppid,24 as pid, 'P' ,'OFL' as catgcode, 31 as earned_points from dual
union
select 3 as ppid,3 as pid, 'B' as code,'ONL' as tier_catgcode, 109 as earned_points from dual
union
select 3 as ppid,32 as pid, 'W' ,'OFL' , 26 as earned_points from dual
union
select 3 as ppid,33 as pid, 'G' ,'OFL', 87 as earned_points from dual
union
select 3 as ppid,34 as pid, 'P' ,'OFL' , 110 as earned_points from dual
union
select 4 as ppid,4 as pid, 'B' as code,'ONL' as catgcode, 109 as earned_points from dual
union
select 4 as ppid,42 as pid, 'W' as code,'OFL' , 26 as earned_points from dual
union
select 4 as ppid,43 as pid, 'G' as code,'OFL' , 87 as earned_points from dual
union
select 4 as ppid,44 as pid, 'P' as code,'OFL' , 56 as earned_points from dual
final (PARENT_PROFILE_ID,PROFILE_ID,catgcode,EARNED_POINTS,BORROWED_POINTS,CERT_POINTS,DISCARD_POINTS,USED)
as (
select A.PPID PARENT_PROFILE_ID,B.PID PROFILE_ID,A.catgcode,B.EARNED_POINTS,BORROWED_POINTS,CERT_POINTS,DISCARD_POINTS,USED
from tbl_SUMMARY a,tbl_link b where a.ppid=b.ppid AND A.catgcode=B.catgcode
ORDER BY PROFILE_ID
select * from final order by 1;
PARENT_PROFILE_ID PROFILE_ID CATGCODE EARNED_POINTS BORROWED_POINTS CERT_POINTS DISCARD_POINTS USED
1 1 ONL 53 47 100 0 100
1 14 OFL 110 0 176 76 100
1 13 OFL 87 0 176 76 100
1 12 OFL 26 0 176 76 100
2 2 ONL 39 61 100 0 100
2 24 OFL 31 0 29 29 100
2 23 OFL 29 0 29 29 100
2 22 OFL 30 0 29 29 100
3 32 OFL 26 0 223 23 200
3 33 OFL 87 0 223 23 200
3 34 OFL 110 0 223 23 200
3 3 ONL 109 0 109 9 100
4 42 OFL 26 0 169 69 100
4 43 OFL 87 0 169 69 100
4 44 OFL 56 0 169 69 100
4 4 ONL 109 0 109 9 100
Need Output as below :
For parent profile 1, whatever i mentioned above is not correct. Borrowed 47 points from OFL to ONL to make ONL and also from OFL category has 176 points remaining after lending to ONL and using only 100 points, remaining 76 points are discarded. Need to deduct these 76 points also from child profiles. Output will be as below.
PARENT_PROFILE_ID PROFILE_ID CATGCODE EARNED_POINTS BORROWED_POINTS CERT_POINTS DISCARD_POINTS USED BURN_PTS EXPIRE_PTS
1 1 ONL 53 47 100 0 100 -53 0
1 12 OFL 26 0 176 76 100 -26 0
1 13 OFL 87 0 176 76 100 -74 -13
1 14 OFL 110 0 176 76 100 -47 -63
For parent profile id 2 --> ONL category has 39 points, so borrowed 61 points from OFL category to make ONL points 100.
Now need to populate tbl_link table at child profile level (i.e. child profiles 22,23,24).
Borrowed 61 points from OFL and need to deduct this points from the profile which has highest earned points, in this case deduct from profile 24 which has 31 points, from profile 22 which has 30 points. Need output like below
PARENT_PROFILE_ID PROFILE_ID CATGCODE EARNED_POINTS BORROWED_POINTS CERT_POINTS DISCARD_POINTS USED BURN_PTS EXPIRE_PTS
2 2 ONL 39 61 100 0 100 -39 0
2 22 OFL 30 0 29 29 100 -30 0
2 23 OFL 29 0 29 29 100 0 -29
2 24 OFL 31 0 29 29 100 -31 0
For parent profile id 3 --> ONL category has 109 points, so no need to borrow points from OFL category
Now need to populate tbl_link table at child profile level (i.e. child profiles 32,33,34).
in this case ONL has 100 points, so move the remaining 9 points will be expired. OFL category has 223 points total. need only 200 points (i.e. mutiple of 100) for our process, 23 points will be expired and has to deduct from the profile which has highest earned points, in this case from profile 34. Output :
PARENT_PROFILE_ID PROFILE_ID CATGCODE EARNED_POINTS BORROWED_POINTS CERT_POINTS DISCARD_POINTS USED BURN_PTS EXPIRE_PTS
3 3 ONL 109 0 109 9 100 -100 -9
3 32 OFL 26 0 223 23 200 -26 0
3 33 OFL 87 0 223 23 200 -87 0
3 34 OFL 110 0 223 23 200 -87 -23
For parent profile id 4 --> ONL category has 109 points, so no need to borrow points from OFL category
Now need to populate tbl_link table at child profile level (i.e. child profiles 42,43,44).
in this case ONL has 100 points, so move the remaining 9 points will be expired. OFL category has 169 points total. need only 100 points (i.e. mutiple of 100) for our process, 69 points will be expired and has to deduct from the profile which has highest earned points, in this case from profile 43. Output :
PARENT_PROFILE_ID PROFILE_ID CATGCODE EARNED_POINTS BORROWED_POINTS CERT_POINTS DISCARD_POINTS USED BURN_PTS EXPIRE_PTS
4 4 ONL 109 0 109 9 100 100 9
4 42 OFL 26 0 169 69 100 -26 0
4 43 OFL 87 0 169 69 100 -18 -69
4 44 OFL 56 0 169 69 100 -56 0
Can someone help with the query. I googled about looping in sql and came to know that Oracle has a feature MODEL to loop in SQL, but i don't have idea on using MODEL clause.
Appreciate your help!
Thanks
SriHi Gurus,
Can someone please help me out.
I've a below tables.
1) tbl_link --> this table contains information at profile level
2) tbl_summary --> this table contains summary at parent profile level derived from tbl_link table
One parent profile contains multiple child profiles and each child profile links to a code (which is B, W, G or P) and the code is linked to a category (i.e. ONL and OFL). In this case code B is linked to category 'ONL' and codes W,G,P linked to OFL category.
ONL category needs 100 points. If it don't have enough points then i need to borrow from OFL category which i'm doing and populating into tbl_summary table at parent profile level.
Now i need to insert data into tbl_link table at profile level with howmany points used, expired based on tbl_summary table. Rule is at the end of month if we add points for each profile in tbl_link table it should come as 0.
with
tbl_SUMMARY as
select 1 as ppid,'ONL' as catgcode, 53 as earned_points,47 BORROWED_POINTS,100 CERT_POINTS,0 DISCARD_POINTS,100 used from dual
union
select 1 as ppid,'OFL' as catgcode, 223 as earned_points,0 BORROWED_POINTS,176 CERT_POINTS,76 DISCARD_POINTS,100 used from dual
union
select 2 as ppid,'ONL' as catgcode, 39 as earned_points,61 BORROWED_POINTS,100 CERT_POINTS,0 DISCARD_POINTS,100 used from dual
union
select 2 as ppid,'OFL' as catgcode, 90 as earned_points,0 BORROWED_POINTS,29 CERT_POINTS,29 DISCARD_POINTS,100 used from dual
union
select 3 as ppid,'ONL' as catgcode, 109 as earned_points,0 BORROWED_POINTS,109 CERT_POINTS,9 DISCARD_POINTS,100 used from dual
union
select 3 as ppid,'OFL' as catgcode, 223 as earned_points,0 BORROWED_POINTS,223 CERT_POINTS,23 DISCARD_POINTS,200 used from dual
union
select 4 as ppid,'ONL' as catgcode, 109 as earned_points,0 BORROWED_POINTS,109 CERT_POINTS,9 DISCARD_POINTS,100 used from dual
union
select 4 as ppid,'OFL' as catgcode, 169 as earned_points,0 BORROWED_POINTS,169 CERT_POINTS,69 DISCARD_POINTS,100 used from dual
tbl_link as
select 1 as ppid,1 as pid, 'B' as code,'ONL' as catgcode, 53 as earned_points from dual
union
select 1 as ppid,12 as pid, 'W' as code,'OFL' as catgcode, 26 as earned_points from dual
union
select 1 as ppid,13 as pid, 'G' as code,'OFL' as catgcode, 87 as earned_points from dual
union
select 1 as ppid,14 as pid, 'P' as code,'OFL' as catgcode, 110 as earned_points from dual
union
select 2 as ppid,2 as pid, 'B' as code,'ONL' as catgcode, 39 as earned_points from dual
union
select 2 as ppid,22 as pid, 'W' ,'OFL' as catgcode, 30 as earned_points from dual
union
select 2 as ppid,23 as pid, 'G' ,'OFL' as catgcode, 29 as earned_points from dual
union
select 2 as ppid,24 as pid, 'P' ,'OFL' as catgcode, 31 as earned_points from dual
union
select 3 as ppid,3 as pid, 'B' as code,'ONL' as tier_catgcode, 109 as earned_points from dual
union
select 3 as ppid,32 as pid, 'W' ,'OFL' , 26 as earned_points from dual
union
select 3 as ppid,33 as pid, 'G' ,'OFL', 87 as earned_points from dual
union
select 3 as ppid,34 as pid, 'P' ,'OFL' , 110 as earned_points from dual
union
select 4 as ppid,4 as pid, 'B' as code,'ONL' as catgcode, 109 as earned_points from dual
union
select 4 as ppid,42 as pid, 'W' as code,'OFL' , 26 as earned_points from dual
union
select 4 as ppid,43 as pid, 'G' as code,'OFL' , 87 as earned_points from dual
union
select 4 as ppid,44 as pid, 'P' as code,'OFL' , 56 as earned_points from dual
final (PARENT_PROFILE_ID,PROFILE_ID,catgcode,EARNED_POINTS,BORROWED_POINTS,CERT_POINTS,DISCARD_POINTS,USED)
as (
select A.PPID PARENT_PROFILE_ID,B.PID PROFILE_ID,A.catgcode,B.EARNED_POINTS,BORROWED_POINTS,CERT_POINTS,DISCARD_POINTS,USED
from tbl_SUMMARY a,tbl_link b where a.ppid=b.ppid AND A.catgcode=B.catgcode
ORDER BY PROFILE_ID
select * from final order by 1;
PARENT_PROFILE_ID PROFILE_ID CATGCODE EARNED_POINTS BORROWED_POINTS CERT_POINTS DISCARD_POINTS USED
1 1 ONL 53 47 100 0 100
1 14 OFL 110 0 176 76 100
1 13 OFL 87 0 176 76 100
1 12 OFL 26 0 176 76 100
2 2 ONL 39 61 100 0 100
2 24 OFL 31 0 29 29 100
2 23 OFL 29 0 29 29 100
2 22 OFL 30 0 29 29 100
3 32 OFL 26 0 223 23 200
3 33 OFL 87 0 223 23 200
3 34 OFL 110 0 223 23 200
3 3 ONL 109 0 109 9 100
4 42 OFL 26 0 169 69 100
4 43 OFL 87 0 169 69 100
4 44 OFL 56 0 169 69 100
4 4 ONL 109 0 109 9 100
Need Output as below :
For parent profile 1, whatever i mentioned above is not correct. Borrowed 47 points from OFL to ONL to make ONL and also from OFL category has 176 points remaining after lending to ONL and using only 100 points, remaining 76 points are discarded. Need to deduct these 76 points also from child profiles. Output will be as below.
PARENT_PROFILE_ID PROFILE_ID CATGCODE EARNED_POINTS BORROWED_POINTS CERT_POINTS DISCARD_POINTS USED BURN_PTS EXPIRE_PTS
1 1 ONL 53 47 100 0 100 -53 0
1 12 OFL 26 0 176 76 100 -26 0
1 13 OFL 87 0 176 76 100 -74 -13
1 14 OFL 110 0 176 76 100 -47 -63
For parent profile id 2 --> ONL category has 39 points, so borrowed 61 points from OFL category to make ONL points 100.
Now need to populate tbl_link table at child profile level (i.e. child profiles 22,23,24).
Borrowed 61 points from OFL and need to deduct this points from the profile which has highest earned points, in this case deduct from profile 24 which has 31 points, from profile 22 which has 30 points. Need output like below
PARENT_PROFILE_ID PROFILE_ID CATGCODE EARNED_POINTS BORROWED_POINTS CERT_POINTS DISCARD_POINTS USED BURN_PTS EXPIRE_PTS
2 2 ONL 39 61 100 0 100 -39 0
2 22 OFL 30 0 29 29 100 -30 0
2 23 OFL 29 0 29 29 100 0 -29
2 24 OFL 31 0 29 29 100 -31 0
For parent profile id 3 --> ONL category has 109 points, so no need to borrow points from OFL category
Now need to populate tbl_link table at child profile level (i.e. child profiles 32,33,34).
in this case ONL has 100 points, so move the remaining 9 points will be expired. OFL category has 223 points total. need only 200 points (i.e. mutiple of 100) for our process, 23 points will be expired and has to deduct from the profile which has highest earned points, in this case from profile 34. Output :
PARENT_PROFILE_ID PROFILE_ID CATGCODE EARNED_POINTS BORROWED_POINTS CERT_POINTS DISCARD_POINTS USED BURN_PTS EXPIRE_PTS
3 3 ONL 109 0 109 9 100 -100 -9
3 32 OFL 26 0 223 23 200 -26 0
3 33 OFL 87 0 223 23 200 -87 0
3 34 OFL 110 0 223 23 200 -87 -23
For parent profile id 4 --> ONL category has 109 points, so no need to borrow points from OFL category
Now need to populate tbl_link table at child profile level (i.e. child profiles 42,43,44).
in this case ONL has 100 points, so move the remaining 9 points will be expired. OFL category has 169 points total. need only 100 points (i.e. mutiple of 100) for our process, 69 points will be expired and has to deduct from the profile which has highest earned points, in this case from profile 43. Output :
PARENT_PROFILE_ID PROFILE_ID CATGCODE EARNED_POINTS BORROWED_POINTS CERT_POINTS DISCARD_POINTS USED BURN_PTS EXPIRE_PTS
4 4 ONL 109 0 109 9 100 100 9
4 42 OFL 26 0 169 69 100 -26 0
4 43 OFL 87 0 169 69 100 -18 -69
4 44 OFL 56 0 169 69 100 -56 0
Can someone help with the query. I googled about looping in sql and came to know that Oracle has a feature MODEL to loop in SQL, but i don't have idea on using MODEL clause.
Appreciate your help!
Thanks
Sri -
I have the privilege of performing a very tedious task.
We have some home grown regular expressions in our company. I now need to expand these regular expressions.
Samples:
a = 0-3
b = Null, 0, 1
Expression: Meaning
1:5: 1,2,3,4,5
1a: 10, 11, 12, 13
1b: 1, 10, 11
1[2,3]ab: 120, 1200, 1201, ....
It get's even more inetersting because there is a possibility of 1[2,3]a.ab
I have created two base queries to aid me in my quest. I am using the SQL MODEL clause to solve this problem. I pretty confident that I should be able to convert evrything into a range and the use one of the MODEL clause listed below.
My only confusion is how do I INCREMENT dynamically. The INCREMENT seems to be a constant in both a FOR and ITERATE statement. I need to figure a way to increment with .01, .1, etc.
Any help will be greatly appreciated.
CODE:
Reference: http://www.sqlsnippets.com/en/topic-11663.html
Objective: Expand a range with ITERATE
WITH t AS
(SELECT '2:4' pt
FROM DUAL
UNION ALL
SELECT '6:9' pt
FROM DUAL)
SELECT pt AS code_expression
-- , KEY
-- , min_key
-- , max_key
, m_1 AS code
FROM t
MODEL
PARTITION BY (pt)
DIMENSION BY ( 0 AS KEY )
MEASURES (
0 AS m_1,
TO_NUMBER(SUBSTR(pt, 1, INSTR(pt, ':') - 1)) AS min_key,
TO_NUMBER(SUBSTR(pt, INSTR(pt, ':') + 1)) AS max_key
RULES
-- UPSERT
ITERATE (100000) UNTIL ( ITERATION_NUMBER = max_key[0] - min_key[0] )
m_1[ITERATION_NUMBER] = min_key[0] + ITERATION_NUMBER
ORDER BY pt, m_1
Explanation:
Line numbers are based on the assupmtion that "WITH t AS" starts at line 5.
If you need detailed information regarding the MODEL clause please refer to
the Refrence site stated above or read some documentation.
Partition-
Line 18: PARTITION BY (pt)
This will make sure that each "KEY" will start at 0 for each value of pt.
Dimension-
Line 19: DIMENSION BY ( 0 AS KEY )
This is necessary for the refrences max_key[0], and min_key[0] to work.
Measures-
Line 21: 0 AS m_1
A space holder for new values.
Line 22: TO_NUMBER(SUBSTR(pt, 1, INSTR(pt, ':') - 1)) AS min_key
The result is '1' for '1:5'.
Line 23: TO_NUMBER(SUBSTR(pt, INSTR(pt, ':') + 1)) AS max_key
The result is '5' for '1:5'.
Rules-
Line 26: UPSERT
This makes it possible for new rows to be created.
Line 27: ITERATE (100000) UNTIL ( ITERATION_NUMBER = max_key[0] - min_key[0] )
This reads ITERATE 100000 times or UNTIL the ITERATION_NUMBER = max_key[0] - min_key[0]
which would be 4 for '1:5', but since the ITERATION_NUMBER starts at 0, whatever follows
is repaeted 5 times.
Line 29: m_1[ITERATION_NUMBER] = min_key[0] + ITERATION_NUMBER
m_1[ITERATION_NUMBER] means m_1[Value of Dimension KEY].
Thus for each row of KEY the m_1 is min_key[0] + ITERATION_NUMBER.
Reference: http://www.sqlsnippets.com/en/topic-11663.html
Objective: Expand a range using FOR
WITH t AS
(SELECT '2:4' pt
FROM DUAL
UNION ALL
SELECT '6:9' pt
FROM DUAL)
, base AS
SELECT pt AS code_expression
, KEY AS code
, min_key
, max_key
, my_increment
, m_1
FROM t
MODEL
PARTITION BY (pt)
DIMENSION BY ( CAST(0 AS NUMBER) AS KEY )
MEASURES (
CAST(NULL AS CHAR) AS m_1,
TO_NUMBER(SUBSTR(pt, 1, INSTR(pt, ':') - 1)) AS min_key,
TO_NUMBER(SUBSTR(pt, INSTR(pt, ':') + 1)) AS max_key,
.1 AS my_increment
RULES
-- UPSERT
m_1[FOR KEY FROM min_key[0] TO max_key[0] INCREMENT 1] = 'Y'
ORDER BY pt, KEY, m_1
SELECT code_expression, code
FROM base
WHERE m_1 = 'Y'
Explanation:
Line numbers are based on the assupmtion that "WITH t AS" starts at line 5.
If you need detailed information regarding the MODEL clause please refer to
the Refrence site stated above or read some documentation.
Partition-
Line 21: PARTITION BY (pt)
This will make sure that each "KEY" will start at 0 for each value of pt.
Dimension-
Line 22: DIMENSION BY ( 0 AS KEY )
This is necessary for the refrences max_key[0], and min_key[0] to work.
Measures-
Line 24: CAST(NULL AS CHAR) AS m_1
A space holder for results.
Line 25: TO_NUMBER(SUBSTR(pt, 1, INSTR(pt, ':') - 1)) AS min_key
The result is '1' for '1:5'.
Line 26: TO_NUMBER(SUBSTR(pt, INSTR(pt, ':') + 1)) AS max_key
The result is '5' for '1:5'.
Line 27: .1 AS my_increment
The INCREMENT I would like to use.
Rules-
Line 30: UPSERT
This makes it possible for new rows to be created.
However seems like it is not necessary.
Line 32: m_1[FOR KEY FROM min_key[0] TO max_key[0] INCREMENT 1] = 'Y'
Where the KE value is between min_key[0] and max_key[0] set the value of m_1 to 'Y'
*/Of course, you can accomplish the same thing without MODEL using an Integer Series Generator like this.
create table t ( min_val number, max_val number, increment_size number );
insert into t values ( 2, 3, 0.1 );
insert into t values ( 1.02, 1.08, 0.02 );
commit;
create table integer_table as
select rownum - 1 as n from all_objects where rownum <= 100 ;
select
min_val ,
increment_size ,
min_val + (increment_size * n) as val
from t, integer_table
where
n between 0 and ((max_val - min_val)/increment_size)
order by 3
MIN_VAL INCREMENT_SIZE VAL
1.02 .02 1.02
1.02 .02 1.04
1.02 .02 1.06
1.02 .02 1.08
2 .1 2
2 .1 2.1
2 .1 2.2
2 .1 2.3
2 .1 2.4
2 .1 2.5
2 .1 2.6
2 .1 2.7
2 .1 2.8
2 .1 2.9
2 .1 3
15 rows selected.--
Joe Fuda
http://www.sqlsnippets.com/ -
Hi Gurus,
I am trying to learn MODEL clause.
How can we achieve the below result in model clause
create table t(c1 number);
insert into t values(11);
insert into t values(30);
insert into t values(45);
select *
from t;
C1
11
30
45 Need to take MIN(C1) as from and MAX(C1) as to values
Then split this range with a gap of 10. Output should be
FROM_C1 TO_C1
11 20
21 30
31 40
41 45How can we do this using MODEL.
I am not getting how to bring the FROM and TO value to the MODEL calsuse, as they are neither DIMENSION nor MEASURE
Thanks.Hi Peter,
I'm quite happy it looks similar to what I've done.
This was my first use of MODEL though:
WITH t AS
SELECT 11 c1 FROM DUAL UNION ALL
SELECT 30 c1 FROM DUAL UNION ALL
SELECT 45 c1 FROM DUAL
t_val AS
SELECT MIN(c1) min_c1
, MAX(c1) max_c1
FROM t
SELECT f AS from_c1, t AS to_c1
FROM t_val model
DIMENSION BY ( 1 AS x )
MEASURES ( min_c1 AS mn
, max_c1 AS mx
, 1 AS f
, 1 AS t
RULES UPSERT
ITERATE (999)UNTIL(t[ITERATION_NUMBER+1]>=mx[1])
f[ITERATION_NUMBER + 1]=f[ITERATION_NUMBER]+ 10,
f[1] = mn[1],
t[ITERATION_NUMBER+1] = LEAST(f[ITERATION_NUMBER+1]+9, mx[1])
ORDER BY f, t;
Output:
FROM_C1 TO_C1
11 20
21 30
31 40
41 45And after seen your example I have understood that it could be simplified by directly using the MIN and MAX value in this way:
WITH t AS
SELECT 11 c1 FROM DUAL UNION ALL
SELECT 30 c1 FROM DUAL UNION ALL
SELECT 45 c1 FROM DUAL
SELECT f AS from_c1, t AS to_c1
FROM t model
DIMENSION BY ( 1 AS x )
MEASURES ( MIN(c1) AS mn
, MAX(c1) AS mx
, 1 AS f
, 1 AS t
RULES UPSERT
ITERATE (999)UNTIL(t[ITERATION_NUMBER + 1]>= mx[1])
f[ITERATION_NUMBER + 1] = mn[1] + 10 * ITERATION_NUMBER,
t[ITERATION_NUMBER + 1] = LEAST(f[ITERATION_NUMBER + 1] + 9, mx[1])
ORDER BY f, t;Regards.
Al
Edited by: Alberto Faenza on Oct 29, 2012 5:48 PM
Added simplified example after seeing Peter's code -
Compute totals and subtotals with model clause
Please help,
I am using the model clause for the first time and need something like this, but no rule definition for every deptno:
SQL> select deptno, empno, ename, sal
2 from emp
3 model
4 dimension by (deptno, empno, ename)
5 measures(sal)
6 rules (
7 sal[10, null, 'ZZ-Sum'] = sum(sal)[10, any, any]
8 ,sal[20, null, 'ZZ-Sum'] = sum(sal)[20, any, any]
9 ,sal[30, null, 'ZZ-Sum'] = sum(sal)[30, any, any]
10 ,sal[null, null, 'ZZ-All'] = sum(sal)[any, any, 'ZZ-Sum']
11 )
12 order by deptno, empno, ename
13 /
DEPTNO EMPNO ENAME SAL
10 7782 CLARK 2450
10 7839 KING 5000
10 7934 MILLER 1300
10 ZZ-Sum 8750
20 7369 SMITH 800
20 7566 JONES 2975
20 7788 SCOTT 3000
20 7876 ADAMS 1100
20 7902 FORD 3000
20 ZZ-Sum 10875
30 7499 ALLEN 1600
30 7521 WARD 1250
30 7654 MARTIN 1250
30 7698 BLAKE 2850
30 7844 TURNER 1500
30 7900 JAMES 950
30 ZZ-Sum 9400
ZZ-All 29025
18 rows selected.Regards
eriMany thanks to you! Your hint shows me, that in this case the model clause is not the right way to go.
The statement below fits exactly my requirements:
SQL> select
2 g.deptno,
3 e.empno,
4 decode(g.grouping_empno,
5 1, decode(g.deptno, null, 'All-Total:', 'Dept-Total:'),
6 e.ename) emp_name,
7 e.job, g.sum_sal salary
8 from (select deptno, empno, grouping(empno) grouping_empno, sum(sal) sum_sal
9 from emp
10 group by rollup(deptno, empno)
11 order by deptno, grouping(empno), empno) g, emp e
12 where g.empno = e.empno (+)
13 /
DEPTNO EMPNO EMP_NAME JOB SALARY
10 7782 CLARK MANAGER 2450
10 7839 KING PRESIDENT 5000
10 7934 MILLER CLERK 1300
10 Dept-Total: 8750
20 7369 SMITH CLERK 800
20 7566 JONES MANAGER 2975
20 7788 SCOTT ANALYST 3000
20 7876 ADAMS CLERK 1100
20 7902 FORD ANALYST 3000
20 Dept-Total: 10875
30 7499 ALLEN SALESMAN 1600
30 7521 WARD SALESMAN 1250
30 7654 MARTIN SALESMAN 1250
30 7698 BLAKE MANAGER 2850
30 7844 TURNER SALESMAN 1500
30 7900 JAMES CLERK 950
30 Dept-Total: 9400
All-Total: 29025
18 rows selected.Regards
eri -
Bin fitting with a counter using both analytics and model clause.
11.2.0.3
This falls under 'just want to figure out how to do it'. Its not critical for work. I want to try to see if its possible to do this with both analytic function and with a model clause. Just to see if its possible. It has been stumping me.
I got the idea to look at this from this article about bin fitting. I have been playing with the model clause and I think you would do something with the 'increment' clause, but I dont see a way to reset it to 1 at a certain point.
http://www.oracle.com/technetwork/issue-archive/2012/12-mar/o22asktom-1518271.html
The case I want to look at is, bin fitting based on a counter and a partition by. In theory this should be simpler than the example in the link.
[code]
create table myrooms (
room_number number,
person_id number);
create unique index myrooms_ind on myrooms(room_number,person_id);
[/code]
Person_id is not unique. So row_number is more appropriate than rank or dense_rank.
Problem: Partition by room_number, assign up to 50 people to a specific group with in the same room. This seems like it could be handled with a row_number() and a window clause, but that is not supported.
I need to basically translate the old procedural counter into sql:
pseudo-code that does not compile that would have a reason to use this logic.
[code]
declare
cursor curGetRoom
select room_number,person_id
from my rooms
order by room_number;
counter number := 1;
vCurrentRoom myroom.room_number%type;
begin
for i in curGetRoom loop
if vCurrentRoom is null then
vCurrentRoom := i.room_number;
elsif vCurrentRoom = i.room_number then
if counter < 51 then counter :=counter+1;
else counter := 1;
else
vCurrentRoom := i.room_number;
counter :=1;
end if;
end;
[/code]
simple partition query., but I dont see a way to limit this to 50 and then start over. Window functions are not supported with row_number()
[code]
select room_number,person_id,row_number() over (partition by room_number order by person_id) rn
from myrooms
[/code]11.2.0.3
This falls under 'just want to figure out how to do it'. Its not critical for work. I want to try to see if its possible to do this with both analytic function and with a model clause. Just to see if its possible. It has been stumping me.
I got the idea to look at this from this article about bin fitting. I have been playing with the model clause and I think you would do something with the 'increment' clause, but I dont see a way to reset it to 1 at a certain point.
http://www.oracle.com/technetwork/issue-archive/2012/12-mar/o22asktom-1518271.html
The case I want to look at is, bin fitting based on a counter and a partition by. In theory this should be simpler than the example in the link.
[code]
create table myrooms (
room_number number,
person_id number);
create unique index myrooms_ind on myrooms(room_number,person_id);
[/code]
Person_id is not unique. So row_number is more appropriate than rank or dense_rank.
Problem: Partition by room_number, assign up to 50 people to a specific group with in the same room. This seems like it could be handled with a row_number() and a window clause, but that is not supported.
I need to basically translate the old procedural counter into sql:
pseudo-code that does not compile that would have a reason to use this logic.
[code]
declare
cursor curGetRoom
select room_number,person_id
from my rooms
order by room_number;
counter number := 1;
vCurrentRoom myroom.room_number%type;
begin
for i in curGetRoom loop
if vCurrentRoom is null then
vCurrentRoom := i.room_number;
elsif vCurrentRoom = i.room_number then
if counter < 51 then counter :=counter+1;
else counter := 1;
else
vCurrentRoom := i.room_number;
counter :=1;
end if;
end;
[/code]
simple partition query., but I dont see a way to limit this to 50 and then start over. Window functions are not supported with row_number()
[code]
select room_number,person_id,row_number() over (partition by room_number order by person_id) rn
from myrooms
[/code] -
Using the Case clause with Model clause
Hello PL SQL gurus
I've used some scripts I've found on these forums to create a mortgage amortization statement. What I am trying to accomplish is getting the script to run a calculation or use a value within a table based upon the value in that table.
Here are the two tables:
CREATE TABLE mortgage_facts (customer VARCHAR2(20), fact VARCHAR2(20),
amount NUMBER(10,3));
INSERT INTO mortgage_facts VALUES ('Smith', 'Loan', 131828.81);
INSERT INTO mortgage_facts VALUES ('Smith', 'Annual_Interest', 3.348);
INSERT INTO mortgage_facts VALUES ('Smith', 'Payments', 72);
INSERT INTO mortgage_facts VALUES ('Smith', 'PaymentAmt', 0);
CREATE TABLE mortgage (customer VARCHAR2(20), pmt_num NUMBER(4), principalp NUMBER(10,3), interestp NUMBER(10,3), mort_balance NUMBER(10,3));
INSERT INTO mortgage VALUES ('Smith',0, 0, 0, 131828.81);
If the value within the table mortgage_facts is zero, I want the script to run a calculation to be used in a MODEL clause. If it is not zero, I would like to use that value instead of the calculation. Below is the script that I am getting an error on (I have bolded the portion in question):
SELECT c, p, to_char(round(m,2),'fm$9999999.00') principal_balance,
to_char(round(pp,2),'fm$9999999.00') towards_principal,
to_char(round(ip,2),'fm$9999999.00') towards_interest,
to_char(round(mp,2),'fm$9999999.00') monthly_payment
FROM MORTGAGE
MODEL --See 1
IGNORE NAV
REFERENCE R ON
*(SELECT customer, fact, amt --See 2*
FROM mortgage_facts
*MODEL DIMENSION BY (customer, fact) MEASURES (amount amt) --See 3*
RULES SEQUENTIAL ORDER
CASE WHEN mortgage_facts.fact = 'PaymentAmt' AND mortage_facts.amt = 0 THEN
*amt[ANY, 'PaymentAmt'] = mortgage_facts.amt*
ELSE
*amt[any, 'PaymentAmt']= (amt[CV(),'Loan']**
*Power(1+ (amt[CV(),'Annual_Interest']/100/12),*
*amt[CV(),'Payments']) **
*(amt[CV(),'Annual_Interest']/100/12)) /*
*(Power(1+(amt[CV(),'Annual_Interest']/100/12),*
*amt[CV(),'Payments']) - 1)*
END
DIMENSION BY (customer cust, fact) measures (amt)
MAIN amortization
PARTITION BY (customer c)
DIMENSION BY (0 p)
MEASURES (principalp pp, interestp ip, mort_balance m, customer mc, 0 mp )
RULES SEQUENTIAL ORDER
ITERATE(1000) UNTIL (ITERATION_NUMBER+1 =
r.amt[mc[0],'Payments'])
(ip[ITERATION_NUMBER+1] = m[CV()-1] *
r.amt[mc[0], 'Annual_Interest']/1200,
mp[ITERATION_NUMBER+1] = r.amt[mc[0], 'PaymentAmt'],
pp[ITERATION_NUMBER+1] = r.amt[mc[0], 'PaymentAmt'] - ip[CV()],
m[ITERATION_NUMBER+1] = m[CV()-1] - pp[CV()]
ORDER BY c, p
Any help is much appreciated. Thank you!!Ok, here we go, one way with iterative model:
select *
from mortgage_facts
model
partition by (Customer)
dimension by (1 p)
measures(loan, payments, INTEREST, PAYMENTAMT, INTERESTPMT, PRINCIPALPMT, balance)
rules iterate(1e9) until (iteration_number+2 >= payments[1])
(loan[iteration_number+2]=loan[1]
,payments[iteration_number+2]=cv(p)-1
,interest[iteration_number+2]=interest[1]
,paymentamt[iteration_number+2]=ROUND(
(LOAN[1] * (INTEREST[1]/12/100)*Power((1+INTEREST[1]/12/100), PAYMENTS[1])/(Power((1+INTEREST[1]/12/100),PAYMENTS[1])-1)), 2)
,INTERESTPMT[iteration_number+2]=round(balance[cv(p)-1]*interest[1]/1200, 2)
,PRINCIPALPMT[iteration_number+2]=paymentamt[cv()]-INTERESTPMT[cv()]
,balance[iteration_number+2]=balance[cv()-1]-PRINCIPALPMT[cv()]
CUSTOMER P LOAN PAYMENTS INTEREST PAYMENTAMT INTERESTPMT PRINCIPALPMT BALANCE
Smith 1 131828.81 72 3.348 0 0 0 131828.81
Smith 2 131828.81 1 3.348 2023.55 367.8 1655.75 130173.06
Smith 3 131828.81 2 3.348 2023.55 363.18 1660.37 128512.69
Smith 4 131828.81 3 3.348 2023.55 358.55 1665 126847.69
Smith 5 131828.81 4 3.348 2023.55 353.91 1669.64 125178.05
Smith 6 131828.81 5 3.348 2023.55 349.25 1674.3 123503.75
Smith 7 131828.81 6 3.348 2023.55 344.58 1678.97 121824.78
Smith 8 131828.81 7 3.348 2023.55 339.89 1683.66 120141.12
Smith 9 131828.81 8 3.348 2023.55 335.19 1688.36 118452.76
Smith 10 131828.81 9 3.348 2023.55 330.48 1693.07 116759.69
Smith 11 131828.81 10 3.348 2023.55 325.76 1697.79 115061.9
Smith 12 131828.81 11 3.348 2023.55 321.02 1702.53 113359.37
Smith 13 131828.81 12 3.348 2023.55 316.27 1707.28 111652.09
Smith 14 131828.81 13 3.348 2023.55 311.51 1712.04 109940.05
.... -
MODEL clause to process a comma separated string
Hi,
I'm trying to parse a comma separated string using SQL so that it will return the parsed values as rows;
eg. 'ABC,DEF GHI,JKL' would return 3 rows;
'ABC'
'DEF GHI'
'JKL'
I'm thinking that I could possibily use the MODEL clause combined with REGULAR expressions to solve this as I've already got a bit of SQL which does the opposite ie. turning the rows into 1 comma separated string;
select id, substr( concat_string, 2 ) as string
from (select 1 id, 'ABC' string from dual union all select 1, 'DEF GHI' from dual union all select 1, 'JKL' from dual)
model
return updated rows
partition by ( id )
dimension by ( row_number() over (partition by id order by string) as position )
measures ( cast(string as varchar2(4000) ) as concat_string )
rules
upsert
iterate( 1000 )
until ( presentv(concat_string[iteration_number+2],1,0) = 0 )
( concat_string[0] = concat_string[0] || ',' || concat_string[iteration_number+1] )
order by id;
Can anyone give me some pointers how to parse the comma separated string using regexp and create as many rows as needed using the MODEL clause?Yes, you could do it without using ITERATE, but FOR ... INCREMENT is pretty much same loop. Couple of improvements:
a) there is no need for CHAINE measure
b) there is no need for CASE in RULES clause
c) NVL can be applies on measures level
with t as (select 1 id, 'ABC,DEF GHI,JKL,DEF GHI,JKL,DEF GHI,JKL,DEF,GHI,JKL' string from dual
union all
select 2,'MNO' string from dual
union all
select 3,null string from dual
SELECT id,
string
FROM T
MODEL
RETURN UPDATED ROWS
partition by (id)
DIMENSION BY (0 POSITION)
MEASURES(
string,
NVL(LENGTH(REGEXP_REPLACE(string,'[^,]+','')),0)+1 NB_MOT
RULES
string[FOR POSITION FROM 1 TO NB_MOT[0] INCREMENT 1] = REGEXP_SUBSTR(string[0],'[^,]+',1,CV(POSITION))
SQL> with t as (select 1 id, 'ABC,DEF GHI,JKL,DEF GHI,JKL,DEF GHI,JKL,DEF,GHI,JKL' string from dual
2 union all
3 select 2,'MNO' string from dual
4 union all
5 select 3,null string from dual
6 )
7 SELECT id,
8 string
9 FROM T
10 MODEL
11 RETURN UPDATED ROWS
12 partition by (id)
13 DIMENSION BY (0 POSITION)
14 MEASURES(
15 string,
16 NVL(LENGTH(REGEXP_REPLACE(string,'[^,]+','')),0)+1 NB_MOT
17 )
18 RULES
19 (
20 string[FOR POSITION FROM 1 TO NB_MOT[0] INCREMENT 1] = REGEXP_SUBSTR(string[0],'[^,]+',1,CV(POSITION))
21 )
22 /
ID STRING
1 ABC
1 DEF GHI
1 JKL
1 DEF GHI
1 JKL
1 DEF GHI
1 JKL
1 DEF
1 GHI
1 JKL
2 MNO
ID STRING
3
12 rows selected.
SQL> SY. -
MODEL clause using CONNECY BY PRIOR
Hello.
I have the following table, CONTEXT_MAPPING:
Name Null? Type
ID NOT NULL NUMBER(38)
CONTEXT_ITEM NOT NULL VARCHAR2(30)
ID_1 NUMBER(38)
ID_2 NUMBER(38)
ID_3 NUMBER(38)
ID_4 NUMBER(38)
ID_5 NUMBER(38)
It's a self referencing table, i.e. ID_1 will refer to an ID from another row in CONTEXT_MAPPING, and the same for ID_2/3/4/5.
Easily illustrated through the following hierarchical data:
ID CONTEXT_ITEM ID1 ID2 ID3 ID4 ID5
1 P_DMA_NDA_ID
2 P_DS_NDA_ID 1
3 P_AST_NDA_ID 2 1
4 P_AGI_ID 3
5 P_ASG_NDA_ID 3
6 P_NTS_FACTS 5 5
7 P_IDE_VALUE 2 1
8 P_EIT_VALUE 2 1
9 P_TRI_TABLE 4 6 7 8
10 P_TRI 9
11 P_PRICE1 6 10 6
12 P_PRICE2 6 10 6
What I want to do, is for any context item, to identify ALL of its dependencies throughout the tree.
For example:
P_PRICE2 has a link to P_NTS_FACTS (ID1 & ID3 = 6) and P_TRI (ID2 = 10)
P_NTS_FACTS has a link to P_ASG_NDA_ID (ID1 & ID2 = 5), which in turn links to P_AST_NDA_ID (ID1 = 3)...
P_TRI has a link to P_TRI_TABLE (ID1 = 9), which in turn links to multiple context items (ID1 = 4, ID2 = 6 etc.) ....
....and so on, until we get to the "root" record, P_DMA_NDA_ID.
So, to see the complete dependency tree for P_PRICE2, I would expect to see a hierarchical result-set like this:
ID CONTEXT_ITEM ID1 ID2 ID3 ID4 ID5
12 P_PRICE2 6 10 6
10 P_TRI 9
9 P_TRI_TABLE 4 6 7 8
4 P_AGI_ID 3
6 P_NTS_FACTS 5 5
5 P_ASG_NDA_ID 3
3 P_AST_NDA_ID 2 1
7 P_IDE_VALUE 2 1
8 P_EIT_VALUE 2 1
2 P_DS_NDA_ID 1
1 P_DMA_NDA_ID
Ideally I want to do this in a single SQL statement - I've tried using CONNECT BY PRIOR in conjunction with LEVEL to do this, but it only performs a hierarchical join for a single child-parent relationship, and I need this to work for up to five children.
Was starting to wonder if I could use the MODEL clause in conjunction with CONNECT BY PRIOR to achieve this - does anyone have any idea whether this type of recursion is possible?
Thanks,
Rayit only performs a hierarchical join for a single child-parent relationshipBeg to differ.
Oracle Database 10g Release 10.2.0.2.0 - Production
SQL> CREATE TABLE context_mapping (
2 id NUMBER(38),
3 context_item VARCHAR2(30),
4 id_1 NUMBER(38),
5 id_2 NUMBER(38),
6 id_3 NUMBER(38),
7 id_4 NUMBER(38),
8 id_5 NUMBER(38));
Table created.
SQL> INSERT INTO context_mapping VALUES (1, 'P_DMA_NDA_ID', NULL, NULL, NULL, NULL, NULL);
1 row created.
SQL> INSERT INTO context_mapping VALUES (2, 'P_DS_NDA_ID', 1, NULL, NULL, NULL, NULL);
1 row created.
SQL> INSERT INTO context_mapping VALUES (3, 'P_AST_NDA_ID', 2, 1, NULL, NULL, NULL);
1 row created.
SQL> INSERT INTO context_mapping VALUES (4, 'P_AGI_ID', 3, NULL, NULL, NULL, NULL);
1 row created.
SQL> INSERT INTO context_mapping VALUES (5, 'P_ASG_NDA_ID', 3, NULL, NULL, NULL, NULL);
1 row created.
SQL> INSERT INTO context_mapping VALUES (6, 'P_NTS_FACTS', 5, 5, NULL, NULL, NULL);
1 row created.
SQL> INSERT INTO context_mapping VALUES (7, 'P_IDE_VALUE', 2, 1, NULL, NULL, NULL);
1 row created.
SQL> INSERT INTO context_mapping VALUES (8, 'P_EIT_VALUE', 2, 1, NULL, NULL, NULL);
1 row created.
SQL> INSERT INTO context_mapping VALUES (9, 'P_TRI_TABLE', 4, 6, 7, 8, NULL);
1 row created.
SQL> INSERT INTO context_mapping VALUES (10, 'P_TRI', 9, NULL, NULL, NULL, NULL);
1 row created.
SQL> INSERT INTO context_mapping VALUES (11, 'P_PRICE1', 6, 10, 6, NULL, NULL);
1 row created.
SQL> INSERT INTO context_mapping VALUES (12, 'P_PRICE2', 6, 10, 6, NULL, NULL);
1 row created.
SQL> SELECT DISTINCT id, context_item, id_1, id_2, id_3, id_4, id_5
2 FROM context_mapping
3 START WITH id = 12
4 CONNECT BY id IN (PRIOR id_1, PRIOR id_2, PRIOR id_3, PRIOR id_4, PRIOR id_5)
5 ORDER BY id DESC;
ID CONTEXT_ITEM ID_1 ID_2 ID_3 ID_4 ID_5
12 P_PRICE2 6 10 6
10 P_TRI 9
9 P_TRI_TABLE 4 6 7 8
8 P_EIT_VALUE 2 1
7 P_IDE_VALUE 2 1
6 P_NTS_FACTS 5 5
5 P_ASG_NDA_ID 3
4 P_AGI_ID 3
3 P_AST_NDA_ID 2 1
2 P_DS_NDA_ID 1
1 P_DMA_NDA_ID
11 rows selected.
SQL> -
Unable to display data no entry in the table without using Model clause
Hi,
I've an urgent requirement described below :
The previously posted Question has been answerted using Model Clause:
Is there any way out to solve it without using Model clause:
I've a table named as "sale" consisting of three columns : empno, sale_amt and sale_date.
(Please ref. The table script with data as given below)
Now if I execute the query :
"select trunc(sale_date) sale_date, sum(sale_amt) total_sale from sale group by trunc(sale_date) order by 1"
then it displays the data for the dates of which there is an entry in that table. But it does not display data for the
date of which there is no entry in that table.
If you run the Table script with data in your schema, then u'll see that there is no entry for 28th. Nov. 2009 in
sale table. Now the above query displays data for rest of the dates as its are in sale table except for 28th. Nov. 2009.
But I need its presence in the query output with a value of "sale_date" as "28th. Nov. 2009" and that of "total_sale" as
"0".
Is there any means to get the result as I require?
Please help ASAP.
Thanks in advance.
Create table script with data:
CREATE TABLE SALE
EMPNO NUMBER,
SALE_AMT NUMBER,
SALE_DATE DATE
SET DEFINE OFF;
Insert into SALE
(EMPNO, SALE_AMT, SALE_DATE)
Values
(100, 1000, TO_DATE('12/01/2009 10:20:10', 'MM/DD/YYYY HH24:MI:SS'));
Insert into SALE
(EMPNO, SALE_AMT, SALE_DATE)
Values
(100, 1000, TO_DATE('11/30/2009 10:21:04', 'MM/DD/YYYY HH24:MI:SS'));
Insert into SALE
(EMPNO, SALE_AMT, SALE_DATE)
Values
(100, 1000, TO_DATE('11/29/2009 10:21:05', 'MM/DD/YYYY HH24:MI:SS'));
Insert into SALE
(EMPNO, SALE_AMT, SALE_DATE)
Values
(100, 1000, TO_DATE('11/26/2009 10:21:06', 'MM/DD/YYYY HH24:MI:SS'));
Insert into SALE
(EMPNO, SALE_AMT, SALE_DATE)
Values
(100, 1000, TO_DATE('11/25/2009 10:21:07', 'MM/DD/YYYY HH24:MI:SS'));
Insert into SALE
(EMPNO, SALE_AMT, SALE_DATE)
Values
(200, 5000, TO_DATE('11/27/2009 10:23:06', 'MM/DD/YYYY HH24:MI:SS'));
Insert into SALE
(EMPNO, SALE_AMT, SALE_DATE)
Values
(200, 4000, TO_DATE('11/29/2009 10:23:08', 'MM/DD/YYYY HH24:MI:SS'));
Insert into SALE
(EMPNO, SALE_AMT, SALE_DATE)
Values
(200, 3000, TO_DATE('11/24/2009 10:23:09', 'MM/DD/YYYY HH24:MI:SS'));
Insert into SALE
(EMPNO, SALE_AMT, SALE_DATE)
Values
(200, 2000, TO_DATE('11/30/2009 10:23:10', 'MM/DD/YYYY HH24:MI:SS'));
Insert into SALE
(EMPNO, SALE_AMT, SALE_DATE)
Values
(300, 7000, TO_DATE('11/24/2009 10:24:19', 'MM/DD/YYYY HH24:MI:SS'));
Insert into SALE
(EMPNO, SALE_AMT, SALE_DATE)
Values
(300, 5000, TO_DATE('11/25/2009 10:24:20', 'MM/DD/YYYY HH24:MI:SS'));
Insert into SALE
(EMPNO, SALE_AMT, SALE_DATE)
Values
(300, 3000, TO_DATE('11/27/2009 10:24:21', 'MM/DD/YYYY HH24:MI:SS'));
Insert into SALE
(EMPNO, SALE_AMT, SALE_DATE)
Values
(300, 2000, TO_DATE('11/29/2009 10:24:22', 'MM/DD/YYYY HH24:MI:SS'));
Insert into SALE
(EMPNO, SALE_AMT, SALE_DATE)
Values
(300, 1000, TO_DATE('11/30/2009 10:24:22', 'MM/DD/YYYY HH24:MI:SS'));
COMMIT;
Any help will be needful for me
Regards,select sale_date,sum(sale_amt) total_sale
from
select empno,0 sale_amt,(sale_date + ao.rn) sale_date
from
select empno,sale_amt,sale_date ,(t.nxt_dt - t.sale_date) diff
from
select empno
,sale_amt,trunc(sale_date) sale_date
,trunc(nvl(lead(sale_date) over (partition by 1 order by sale_date),sale_date)) nxt_dt
from sale
) t
where (t.nxt_dt - t.sale_date) >1
) rec,(select rownum rn from user_objects where rownum<=200) ao
where ao.rn <=(rec.diff-1)
union all
select empno,sale_amt,trunc(sale_date) sale_date
from sale
group by sale_date
order by 1;
~~~~Guess this will serve the purpose...
Cheers Arpan -
Pivoting using Model Clause Vs pivoting using Aggregate Fun(Case) statement
Hi,
I just wanted to know which option is better for pivoting the data if the data is like:
Grp1 Grp2 Day_week Sales
1 1 Sun 200
1 1 Mon 100
1 2 Sun 1000
and so on...
The output should be:
Grp1 Grp2 Sun Mon ......
1 1 200 100.....
1 2 1000 NULL....
I have tested the same using sum(decode...) method and also model clause:
select grp1, grp2, sum(decode(day_week,'SUN',sales)) SUNDAY , sum(decode(day_week,'MON',sales)) MONDAY from pivot
group by grp1, grp2
order by grp1, grp2
select grp1, grp2, sun , mon, tue, wed, thr, fri, sat
from pivot
model -- UNIQUE SINGLE REFERENCE
return updated rows
partition by (grp1, grp2)
dimension by ( day_week)
measures( result, 0 mon, 0 tue, 0 wed, 0 thr,0 fri, 0 sat, 0 sun)
RULES upsert
mon[0]= sales['MON'],
tue[0]= sales['TUE'],
wed[0]= sales['WED'],
thr[0]= sales['THR'],
fri[0]= sales['FRI'],
sat[0]= sales['SAT'],
sun[0]= sales['SUN']
) order by grp1, grp2
There are 4K records in the table. The first query is taking app (.125 seconds) and the second query (.230 seconds).
Pls tell how the model clause can give better performance and I want to use it for pivoting in all my APIs.
Regards
Rajiv> I read somewhere while searching on net.
And now you can't find it anymore? I wouldn't believe anything you read somewhere while searching on net, unless it has some kind of proof attached.
> You pls tell is it so or it depends upon volume of data.
Also i tested on some data and reults were better in
case of using normal startegy rather than model.(case
provided above).
So you have tested it yourself already. The model clause is great in a few cases (string aggregation, calculating values based on calculated values), but this doesn't seem to be one of them. On 11g you might want to consider the PIVOT operator.
Regards,
Rob. -
Using MODEL clause and COUNT for not numeric data columns....
Hi ,
Is it possible somehow to use the COUNT function to transform a non-numeric data column to a numeric data value (a counter) and be used in a MODEL clause....????
For example , i tried the following in the emp table of SCOTT dataschema with no desired result...
SQL> select deptno , empno , hiredate from emp;
DEPTNO EMPNO HIREDATE
20 7369 18/12/1980
30 7499 20/02/1981
30 7521 22/02/1981
20 7566 02/04/1981
30 7654 28/09/1981
30 7698 01/05/1981
10 7782 09/06/1981
20 7788 18/04/1987
10 7839 17/11/1981
30 7844 08/09/1981
20 7876 21/05/1987
30 7900 03/12/1981
20 7902 03/12/1981
10 7934 23/01/1982
14 rows selected Now , i want to use the MODEL clause in order to 'predict' the number of employees who were going to be hired in the 1990 per deptno...
So , i have constructed the following query which , as expected, does not return the desired results....
SQL> select deptno , month , year , count_
2 from
3 (
4 select deptno , to_number(to_char(hiredate,'mm')) month ,
5 to_number(to_char(hiredate , 'rrrr')) year , count(ename) count_
6 from emp
7 group by deptno , to_number(to_char(hiredate,'mm')) ,
8 to_number(to_char(hiredate , 'rrrr'))
9 )
10 model
11 partition by(deptno)
12 dimension by (month , year)
13 measures (count_ )
14 (
15 count_[1,1990]=count_[1,1982]+count_[11,1982]
16 )
17 /
DEPTNO MONTH YEAR COUNT_
30 5 1981 1
30 12 1981 1
30 2 1981 2
30 9 1981 2
30 1 1990
20 4 1987 1
20 5 1987 1
20 4 1981 1
20 12 1981 1
20 12 1980 1
20 1 1990
10 6 1981 1
10 11 1981 1
10 1 1982 1
10 1 1990 As you see , the measures for the 1990 year is null...because the measure(the count(deptno)) is computed via the group by and not by the MODEL clause...
How should i transform the above query... so as the "count_[1,1982]+count_[11,1982]" will return non-null results per deptno...????
Thanks , a lot
SimonConnected to Oracle Database 10g Express Edition Release 10.2.0.1.0
Connected as hr
SQL>
SQL> SELECT department_id, MONTH, YEAR, count_
2 FROM (SELECT e.department_id
3 ,to_number(to_char(e.hire_date, 'mm')) MONTH
4 ,to_number(to_char(e.hire_date, 'rrrr')) YEAR
5 ,COUNT(e.first_name) count_
6 FROM employees e
7 WHERE e.department_id = 20
8 GROUP BY e.department_id
9 ,to_number(to_char(e.hire_date, 'mm'))
10 ,to_number(to_char(e.hire_date, 'rrrr')));
DEPARTMENT_ID MONTH YEAR COUNT_
20 8 1997 1
20 2 1996 1
SQL> --
SQL> SELECT department_id, MONTH, YEAR, count_
2 FROM (SELECT e.department_id
3 ,to_number(to_char(e.hire_date, 'mm')) MONTH
4 ,to_number(to_char(e.hire_date, 'rrrr')) YEAR
5 ,COUNT(e.first_name) count_
6 FROM employees e
7 WHERE e.department_id = 20
8 GROUP BY e.department_id
9 ,to_number(to_char(e.hire_date, 'mm'))
10 ,to_number(to_char(e.hire_date, 'rrrr')))
11 model
12 PARTITION BY(department_id)
13 dimension BY(MONTH, YEAR)
14 measures(count_)(
15 count_ [1, 1990] = count_ [2, 1996] + count_ [8, 1997]
16 );
DEPARTMENT_ID MONTH YEAR COUNT_
20 8 1997 1
20 2 1996 1
20 1 1990 2
SQL> ---
SQL> SELECT department_id, MONTH, YEAR, count_
2 FROM (SELECT e.department_id
3 ,to_number(to_char(e.hire_date, 'mm')) MONTH
4 ,to_number(to_char(e.hire_date, 'rrrr')) YEAR
5 ,COUNT(e.first_name) count_
6 FROM employees e
7 GROUP BY e.department_id
8 ,to_number(to_char(e.hire_date, 'mm'))
9 ,to_number(to_char(e.hire_date, 'rrrr')))
10 model ignore nav
11 PARTITION BY(department_id)
12 dimension BY(MONTH, YEAR)
13 measures(count_)(
14 count_ [1, 1990] = count_ [2, 1996] + count_ [8, 1997]
15 );
DEPARTMENT_ID MONTH YEAR COUNT_
100 8 1994 2
30 12 1997 1
100 3 1998 1
30 7 1997 1
5 1999 1
30 12 1994 1
30 11 1998 1
30 5 1995 1
100 9 1997 2
100 12 1999 1
30 8 1999 1
1 1990 0
30 1 1990 0
100 1 1990 0
90 9 1989 1
20 8 1997 1
70 6 1994 1
93 rows selected
SQL> -
Trying to understand the MODEL clause
Hi All,
I'm finally biting the bullet and learning how to use the model clause, but I'm having a bit of trouble.
The following example data comes from a book "Advanced CQL Functions in Oracle 10g".
with sales1 as (select 'blueberries' product
,'pensacola' location
,9000 amount
,2001 year
from dual
union all
select 'cotton', 'pensacola',16000,2001 from dual
union all
select 'lumber','pensacola',3500,2001 from dual
union all
select 'cotton','mobile',24000,2001 from dual
union all
select 'lumber', 'mobile',2800,2001 from dual
union all
select 'plastic','mobile',32000,2001 from dual
union all
select 'blueberries','pensacola',9000,2002 from dual
union all
select 'cotton', 'pensacola',16000,2002 from dual
union all
select 'lumber','pensacola',3500,2002 from dual
union all
select 'cotton','mobile',24000,2002 from dual
union all
select 'lumber', 'mobile',2800,2002 from dual
union all
select 'plastic','mobile',32000,2002 from dual
union all
select 'blueberries','pensacola',9000,2003 from dual
union all
select 'cotton', 'pensacola',16000,2003 from dual
union all
select 'lumber','pensacola',3500,2003 from dual
union all
select 'cotton','mobile',24000,2003 from dual
union all
select 'lumber', 'mobile',2800,2003 from dual
union all
select 'plastic','mobile',32000,2003 from dual
select location, product, year, s
from sales1
model
--return updated rows
partition by (product)
dimension by (location,year)
measures (amount s) ignore nav
(s['pensacola',2003] = sum(s)['pensacola',cv() > cv()-1])I would have expected the measures clause to return the sum of all amounts for pensacola where the year > 2003 - 1 = 2002. which would make the total for [blueberries,2003] = 1800, but instead it comes out as 27000, apparently summing all values for blueberries for that partition.... equivalent to sum(s)['pensacola',ANY].
how would I go about making s['pensacola',2003] = the sum of itself plus the previous row?
I realise I can do
s['pensacola',cv()]+s['pensacola',cv()-1]but I'm really trying to understand why what I have doesn't appear to work the way I expect.Because
(s['pensacola',2003] = sum(s)['pensacola',cv() > cv()-1])
means
(s['pensacola',2003] = sum(s)['pensacola',cv(year) > cv(year)-1])
means
(s['pensacola',2003] = sum(s)['pensacola',2003 > 2003-1])
means
(s['pensacola',2003] = sum(s)['pensacola',2003 > 2002])
means
(s['pensacola',2003] = sum(s)['pensacola',year is any])
s['pensacola',cv()]+s['pensacola',cv()-1]
means
sum(s)['pensacola',year between cv()-1 and cv()] -
CV() in Model clause
Hi,
Although this query returns 6 rows of data (2 rows having data, and rest of the rows are having NULL values), where as my requirement is to to get the following output:
RUN_SEQ
USAGE_PERIOD_START_DATE_D
USAGE_PERIOD_END_DATE_D
1
01-Jan-13
30-Jan-13
2
31-Jan-13
01-Mar-13
3
02-Mar-13
31-Mar-13
4
01-Apr-13
30-Apr-13
5
01-May-13
30-May-13
6
31-May-13
29-Jun-13
select RUN_SEQ, USAGE_PERIOD_START_DATE_D, USAGE_PERIOD_END_DATE_D
from dual
model
dimension by (1 as idx)
MEASURES (
1 as RUN_SEQ,
TO_DATE('20130101','YYYYMMDD') AS USAGE_PERIOD_START_DATE_D,
TO_DATE('20130101','YYYYMMDD')+29 AS USAGE_PERIOD_END_DATE_D
rules upsert all (
RUN_SEQ[for idx from 2 to 6 increment 1] = RUN_SEQ[cv()-1]+1,
USAGE_PERIOD_START_DATE_D[for idx from 2 to 6 increment 1] = USAGE_PERIOD_END_DATE_D[cv()-1]+1,
USAGE_PERIOD_END_DATE_D[for idx from 2 to 6 increment 1] = USAGE_PERIOD_START_DATE_D[cv()]+29
order by idx;
Could anyone please suggest where am I going wrong.
Thanks & Regards,
PawanYou may also control the "rules-flow" by yourself and rewrite it as an iterative model
select RUN_SEQ, USAGE_PERIOD_START_DATE_D, USAGE_PERIOD_END_DATE_D
from dual
model
dimension by (1 as idx)
MEASURES (
1 as RUN_SEQ,
TO_DATE('20130101','YYYYMMDD') AS USAGE_PERIOD_START_DATE_D,
TO_DATE('20130101','YYYYMMDD')+29 AS USAGE_PERIOD_END_DATE_D
rules iterate (5) (
RUN_SEQ[iteration_number+2] = RUN_SEQ[iteration_number+1] + 1,
USAGE_PERIOD_START_DATE_D[iteration_number+2] = USAGE_PERIOD_END_DATE_D[iteration_number+1]+1,
USAGE_PERIOD_END_DATE_D[iteration_number+2] = USAGE_PERIOD_START_DATE_D[iteration_number+2]+29
order by idx;
Maybe you are looking for
-
Notes do not sync from iCloud to iPhone 4s AND Notes disappear from iPhone
My notes are not syncing from iCloud to my iPhone 4s. I turned Notes 'off' on my iPhone (Settings>iCloud>Notes), then back on. Now all of my notes on my iPhone have DISAPPEARED. Restarted my 4s - no change. I created a test Note on iCloud.com and it
-
HP photosmart 109a printer - Not printing black ink
Hi. I am having problems with my HP photosmart 109a printer. It is printing in the other 3 colours but is not printing from the black cartridge. I have tried replacing the black cartridge twice now with 2 brand new cartridges. I have also tried clean
-
The Boot Configuration Data file is missing requires Information
My ideapad U310 doesn't boot any more after the boot procedure was interrupted by power outage. A blue screen shows the following: Recovery Your PC needs to be repaired The Boot Configuration Data file is missing some required information. File: \BCD
-
Sub-contracting at two different vendors directly monitored by the company.
Initially the raw material is supplied to a sub-contracting vendor A by the company to process it. After vendor A finishes processing it, the material will be shipped by vendor A to vendor B on behalf of the company for further processing which marks
-
Windows will NOT start up. Will start, BUT log itself off ASAP
I have an S10 netbook. Recently it caught a virus so I figured that the easiest thing to do was to do a system restore to an earlier time. The system restoring process went like it should; however, it wasn't successful. Once the system restarted and