This section presents tutorials on the MODEL clause of the SELECT command. Introduced in Oracle 10g, the MODEL clause is a powerful feature that gives you the ability to change any cell in the query's result set using data from any other cell (similar to the way a spreadsheet works). It also adds procedural features to SQL previously available only through PL/SQL calls.
For example, with MODEL you can take a simple table like this
KEY GROUP_1 GROUP_2 DATE_VAL NUM_VAL ------ ---------- ---------- ---------- ------- 1 A a1 2005-01-01 100 2 A a2 2005-06-12 200 3 A a3 300 4 B a1 2006-02-01 5 B a2 2006-06-12 300 6 B a3 2005-01-01 100 7 C a1 2006-06-12 100 8 C a2 9 a1 2005-02-01 200 10 a2 2005-02-01 800
and, with a single command, create a report containing ad-hoc totals like this.
set null "" select case when key like 'Total%' then key else null end as total , group_1 , group_2 , num_val from t model dimension by ( cast(key as varchar2(20)) as key , nvl( group_1, 'n/a' ) as group_1 , nvl( group_2, 'n/a' ) as group_2 ) measures( num_val ) rules ( num_val[ 'Total 1 - A + C', null, null ] = sum(num_val)[any,group_1 in ('A','C'),any] , num_val[ 'Total 2 - A + a2', null, null ] = sum(num_val)[any,'A',any] + sum(num_val)[any,group_1 <> 'A','a2'] , num_val[ 'Total 3 - n/a', null, null ] = sum(num_val)[any,'n/a',any] , num_val[ 'Total 4 - a1 + a3', null, null ] = sum(num_val)[any,any,group_2 in ('a1','a3')] ) order by group_1 , group_2 , total nulls first ;
TOTAL GROUP_1 GROUP_2 NUM_VAL -------------------- ---------- ---------- ------- A a1 100 A a2 200 A a3 300 B a1 B a2 300 B a3 100 C a1 100 C a2 n/a a1 200 n/a a2 800 Total 1 - A + C 700 Total 2 - A + a2 1700 Total 3 - n/a 1000 Total 4 - a1 + a3 800
You can also use MODEL'S procedural features to produce results that are difficult, inefficient, or impossible to do with a non-MODEL SELECT command. Here is an example.
set null "(null)" column string format a40 select group_1, substr( string, 2 ) as string from t where num_val is not null model return updated rows partition by ( group_1 ) dimension by ( row_number() over (partition by group_1 order by num_val) as position ) measures ( cast( num_val as varchar2(65) ) as string ) -- Note 1 rules upsert iterate( 6 ) until ( presentv(string[iteration_number+2],1,0) = 0 ) ( string[0] = string[0] || ',' || string[iteration_number+1] ) order by group_1 ;
GROUP_1 STRING ---------- ---------------------------------------- A 100,200,300 B 100,300 C 100 (null) 200,800
(This last technique is explained fully in another section of SQL Snippets at Rows to String: MODEL Method 1.)
Though powerful, the MODEL clause is also somewhat complex and this can be intimidating when you read about it for the first time. The tutorials to follow will therefore present very simple MODEL examples to help you quickly become comfortable with its many features.
Before continuing it is important to know that everything in the MODEL clause is evaluated after all other clauses in the query, except for SELECT DISTINCT and ORDER BY. Knowing this will help you better understand the examples in this section's tutorials.