d:\orasql>sqlplus test@ora12c
SQL*Plus: Release 11.2.0.4.0 Production on Mon Aug 11 11:23:00 2014
Copyright (c) 1982, 2013, Oracle. All rights reserved.
Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
>set lines 100
>descr hr.employees
Name Null? Type
----------------------------------------------------- -------- ---------------
EMPLOYEE_ID NOT NULL NUMBER(6)
FIRST_NAME VARCHAR2(20)
LAST_NAME NOT NULL VARCHAR2(25)
EMAIL NOT NULL VARCHAR2(25)
PHONE_NUMBER VARCHAR2(20)
HIRE_DATE NOT NULL DATE
JOB_ID NOT NULL VARCHAR2(10)
SALARY NUMBER(8,2)
COMMISSION_PCT NUMBER(2,2)
MANAGER_ID NUMBER(6)
DEPARTMENT_ID NUMBER(4)
>create table employees as select * from hr.employees;
Table created.
>
select employee_id, first_name, last_name, salary, manager_id, department_id
from employees;
EMPLOYEE_ID FIRST_NAME LAST_NAME SALARY MANAGER_ID DEPARTMENT_ID
----------- -------------------- ------------------------- ---------- ---------- -------------
198 Donald OConnell 2600 124 50
199 Douglas Grant 2600 124 50
200 Jennifer Whalen 4400 101 10
201 Michael Hartstein 13000 100 20
202 Pat Fay 6000 201 20
203 Susan Mavris 6500 101 40
204 Hermann Baer 10000 101 70
205 Shelley Higgins 12008 101 110
206 William Gietz 8300 205 110
100 Steven King 24000 90
101 Neena Kochhar 17000 100 90
102 Lex De Haan 17000 100 90
103 Alexander Hunold 9000 102 60
104 Bruce Ernst 6000 103 60
105 David Austin 4800 103 60
106 Valli Pataballa 4800 103 60
107 Diana Lorentz 4200 103 60
108 Nancy Greenberg 12008 101 100
109 Daniel Faviet 9000 108 100
110 John Chen 8200 108 100
111 Ismael Sciarra 7700 108 100
112 Jose Manuel Urman 7800 108 100
113 Luis Popp 6900 108 100
114 Den Raphaely 11000 100 30
115 Alexander Khoo 3100 114 30
116 Shelli Baida 2900 114 30
117 Sigal Tobias 2800 114 30
118 Guy Himuro 2600 114 30
119 Karen Colmenares 2500 114 30
120 Matthew Weiss 8000 100 50
121 Adam Fripp 8200 100 50
122 Payam Kaufling 7900 100 50
123 Shanta Vollman 6500 100 50
124 Kevin Mourgos 5800 100 50
125 Julia Nayer 3200 120 50
126 Irene Mikkilineni 2700 120 50
127 James Landry 2400 120 50
128 Steven Markle 2200 120 50
129 Laura Bissot 3300 121 50
130 Mozhe Atkinson 2800 121 50
131 James Marlow 2500 121 50
132 TJ Olson 2100 121 50
133 Jason Mallin 3300 122 50
134 Michael Rogers 2900 122 50
135 Ki Gee 2400 122 50
136 Hazel Philtanker 2200 122 50
137 Renske Ladwig 3600 123 50
138 Stephen Stiles 3200 123 50
139 John Seo 2700 123 50
140 Joshua Patel 2500 123 50
141 Trenna Rajs 3500 124 50
142 Curtis Davies 3100 124 50
143 Randall Matos 2600 124 50
144 Peter Vargas 2500 124 50
145 John Russell 14000 100 80
146 Karen Partners 13500 100 80
147 Alberto Errazuriz 12000 100 80
148 Gerald Cambrault 11000 100 80
149 Eleni Zlotkey 10500 100 80
150 Peter Tucker 10000 145 80
151 David Bernstein 9500 145 80
152 Peter Hall 9000 145 80
153 Christopher Olsen 8000 145 80
154 Nanette Cambrault 7500 145 80
155 Oliver Tuvault 7000 145 80
156 Janette King 10000 146 80
157 Patrick Sully 9500 146 80
158 Allan McEwen 9000 146 80
159 Lindsey Smith 8000 146 80
160 Louise Doran 7500 146 80
161 Sarath Sewall 7000 146 80
162 Clara Vishney 10500 147 80
163 Danielle Greene 9500 147 80
164 Mattea Marvins 7200 147 80
165 David Lee 6800 147 80
166 Sundar Ande 6400 147 80
167 Amit Banda 6200 147 80
168 Lisa Ozer 11500 148 80
169 Harrison Bloom 10000 148 80
170 Tayler Fox 9600 148 80
171 William Smith 7400 148 80
172 Elizabeth Bates 7300 148 80
173 Sundita Kumar 6100 148 80
174 Ellen Abel 11000 149 80
175 Alyssa Hutton 8800 149 80
176 Jonathon Taylor 8600 149 80
177 Jack Livingston 8400 149 80
178 Kimberely Grant 7000 149
179 Charles Johnson 6200 149 80
180 Winston Taylor 3200 120 50
181 Jean Fleaur 3100 120 50
182 Martha Sullivan 2500 120 50
183 Girard Geoni 2800 120 50
184 Nandita Sarchand 4200 121 50
185 Alexis Bull 4100 121 50
186 Julia Dellinger 3400 121 50
187 Anthony Cabrio 3000 121 50
188 Kelly Chung 3800 122 50
189 Jennifer Dilly 3600 122 50
190 Timothy Gates 2900 122 50
191 Randall Perkins 2500 122 50
192 Sarah Bell 4000 123 50
193 Britney Everett 3900 123 50
194 Samuel McCain 3200 123 50
195 Vance Jones 2800 123 50
196 Alana Walsh 3100 124 50
197 Kevin Feeney 3000 124 50
107 rows selected.
>
>
select employee_id, salary
from employees
model
dimension by (employee_id)
measures (salary)
();
EMPLOYEE_ID SALARY
----------- ----------
198 2600
199 2600
200 4400
201 13000
202 6000
203 6500
204 10000
205 12008
206 8300
100 24000
101 17000
102 17000
103 9000
104 6000
105 4800
106 4800
107 4200
108 12008
109 9000
110 8200
111 7700
112 7800
113 6900
114 11000
115 3100
116 2900
117 2800
118 2600
119 2500
120 8000
121 8200
122 7900
123 6500
124 5800
125 3200
126 2700
127 2400
128 2200
129 3300
130 2800
131 2500
132 2100
133 3300
134 2900
135 2400
136 2200
137 3600
138 3200
139 2700
140 2500
141 3500
142 3100
143 2600
144 2500
145 14000
146 13500
147 12000
148 11000
149 10500
150 10000
151 9500
152 9000
153 8000
154 7500
155 7000
156 10000
157 9500
158 9000
159 8000
160 7500
161 7000
162 10500
163 9500
164 7200
165 6800
166 6400
167 6200
168 11500
169 10000
170 9600
171 7400
172 7300
173 6100
174 11000
175 8800
176 8600
177 8400
178 7000
179 6200
180 3200
181 3100
182 2500
183 2800
184 4200
185 4100
186 3400
187 3000
188 3800
189 3600
190 2900
191 2500
192 4000
193 3900
194 3200
195 2800
196 3100
197 3000
107 rows selected.
>
>
select employee_id, salary
from employees
model
dimension by (employee_id)
measures (salary)
()
order by employee_id
fetch first 10 rows only;
EMPLOYEE_ID SALARY
----------- ----------
100 24000
101 17000
102 17000
103 9000
104 6000
105 4800
106 4800
107 4200
108 12008
109 9000
10 rows selected.
>
>
select employee_id,
decode(employee_id, 100, salary+1000, salary) salary
from employees
order by employee_id
fetch first 10 rows only;
EMPLOYEE_ID SALARY
----------- ----------
100 25000
101 17000
102 17000
103 9000
104 6000
105 4800
106 4800
107 4200
108 12008
109 9000
10 rows selected.
>
>
select employee_id, salary
from employees
model
dimension by (employee_id)
measures (salary)
RULES (
SALARY[employee_id = 100] = SALARY[employee_id = 100] + 1000
)
order by employee_id
fetch first 10 rows only;
EMPLOYEE_ID SALARY
----------- ----------
100 25000
101 17000
102 17000
103 9000
104 6000
105 4800
106 4800
107 4200
108 12008
109 9000
10 rows selected.
>
>
select employee_id, salary
from employees
order by employee_id
fetch first 10 rows only;
EMPLOYEE_ID SALARY
----------- ----------
100 24000
101 17000
102 17000
103 9000
104 6000
105 4800
106 4800
107 4200
108 12008
109 9000
10 rows selected.
>
>
select employee_id, salary
from employees
model
dimension by (employee_id)
measures (salary)
RULES (
salary[for employee_id from 100 to 105 INCREMENT 1] =
salary[for employee_id from 100 to 105 INCREMENT 1] + 1000
)
order by employee_id
fetch first 10 rows only;
select employee_id, salary
*
ERROR at line 1:
ORA-32622: illegal multi-cell reference
>
>
select employee_id, salary
from employees
model
dimension by (employee_id)
measures (salary)
RULES (
salary[for employee_id from 100 to 105 INCREMENT 1] = 1000
)
order by employee_id
fetch first 10 rows only;
EMPLOYEE_ID SALARY
----------- ----------
100 1000
101 1000
102 1000
103 1000
104 1000
105 1000
106 4800
107 4200
108 12008
109 9000
10 rows selected.
>
The data was changed for the employee_id from 100 to 105, but the value here is set to 1000. The selection criteria works. The relative calculation doesn't. So how do we get the actual value on the right side of the equals sign of the calculating row?
>
select employee_id, salary
from employees
model
dimension by (employee_id)
measures (salary)
RULES (
salary[for employee_id from 100 to 105 INCREMENT 1] = salary[cv()] + 1000
)
order by employee_id
fetch first 10 rows only;
EMPLOYEE_ID SALARY
----------- ----------
100 25000
101 18000
102 18000
103 10000
104 7000
105 5800
106 4800
107 4200
108 12008
109 9000
10 rows selected.
>
>
select employee_id, salary
from employees
model
dimension by (employee_id)
measures (salary)
RULES (
salary[for employee_id in (100, 102, 104, 105)] = salary[cv()] + 1000
)
order by employee_id
fetch first 10 rows only;
EMPLOYEE_ID SALARY
----------- ----------
100 25000
101 17000
102 18000
103 9000
104 7000
105 5800
106 4800
107 4200
108 12008
109 9000
10 rows selected.
>
>
select level+99 criteria from dual where level not in (2, 4) connect by level <= 6;
CRITERIA
----------
100
102
104
105
>
select employee_id, salary
from employees
model
dimension by (employee_id)
measures (salary)
RULES (
salary[for employee_id in (
select level+99 from dual where level not in (2, 4) connect by level <= 6 )] =
salary[cv()] + 1000
)
order by employee_id
fetch first 10 rows only;
EMPLOYEE_ID SALARY
----------- ----------
100 25000
101 17000
102 18000
103 9000
104 7000
105 5800
106 4800
107 4200
108 12008
109 9000
10 rows selected.
>
>
select employee_id, salary
from employees
model
dimension by (employee_id)
measures (salary)
RULES (
salary[any] = salary[cv()] + 1000
)
order by employee_id
fetch first 10 rows only;
EMPLOYEE_ID SALARY
----------- ----------
100 25000
101 18000
102 18000
103 10000
104 7000
105 5800
106 5800
107 5200
108 13008
109 10000
10 rows selected.
>
>
select employee_id, salary + 1000 salary
from employees
order by employee_id
fetch first 10 rows only;
EMPLOYEE_ID SALARY
----------- ----------
100 25000
101 18000
102 18000
103 10000
104 7000
105 5800
106 5800
107 5200
108 13008
109 10000
10 rows selected.
>
And yes, it would work:
Use lead/lag for next salary and ... um, use first_value (since lead/lag doesn't have a windowing clause) for third next salary, wrap that inside a with clause (also called a cte), and then select from that cte and calculate the result
>
with cte as (
select employee_id, salary,
lead(salary) over (order by employee_id) next_salary,
-- lead(salary) over (order by employee_id
-- rows
-- between 3 following
-- and unbounded following) third_next_salary
first_value(salary) over (order by employee_id
rows
between 3 following
and unbounded following) third_next_salary
from employees
)
select employee_id, salary, next_salary, third_next_salary,
salary + next_salary + third_next_salary as calculated_salary
from cte
order by employee_id
fetch first 10 rows only;
EMPLOYEE_ID SALARY NEXT_SALARY THIRD_NEXT_SALARY CALCULATED_SALARY
----------- ---------- ----------- ----------------- -----------------
100 24000 17000 9000 50000
101 17000 17000 6000 40000
102 17000 9000 4800 30800
103 9000 6000 4800 19800
104 6000 4800 4200 15000
105 4800 4800 12008 21608
106 4800 4200 9000 18000
107 4200 12008 8200 24408
108 12008 9000 7700 28708
109 9000 8200 7800 25000
10 rows selected.
>
>
select employee_id, salary
from employees
model
dimension by (employee_id)
measures (salary)
RULES (
salary[any] order by employee_id asc =
salary[cv()] + salary[cv() +1] + salary[cv() +3]
)
order by employee_id
fetch first 10 rows only;
EMPLOYEE_ID SALARY
----------- ----------
100 50000
101 40000
102 30800
103 19800
104 15000
105 21608
106 18000
107 24408
108 28708
109 25000
10 rows selected.
>
>
select employee_id, salary
from employees
model
dimension by (employee_id)
measures (salary)
RULES (
salary[ 1 ] = 1000
)
order by employee_id
fetch first 10 rows only;
EMPLOYEE_ID SALARY
----------- ----------
1 1000
100 24000
101 17000
102 17000
103 9000
104 6000
105 4800
106 4800
107 4200
108 12008
10 rows selected.
>
>
select level+99 criteria from dual where level not in (2, 4) connect by level <= 6;
CRITERIA
----------
100
102
104
105
>
This can also be done with the model clause and the single column for loop. I'll start with the complete range: from 100 to 105.
>
select criteria
from dual
model
dimension by (100 criteria)
measures (0 x)
RULES (
x[for criteria from 100 to 105 increment 1] = 0
);
CRITERIA
----------
100
101
102
103
104
105
6 rows selected.
>
There are a few tricks in play here:
>
select criteria
from dual
model
dimension by (0 criteria)
measures (0 x)
RULES (
x[for criteria from 100 to 105 increment 1] = 0
);
CRITERIA
----------
0
100
101
102
103
104
105
7 rows selected.
>
One way of solving this was by using the starting value or ... by changing the default model clause behaviour in what rows it returns.
>
select employee_id
from employees
model
return updated rows
dimension by (employee_id)
measures (0 x)
RULES (
x[for employee_id from 1 to 10 increment 1] = 0
);
EMPLOYEE_ID
-----------
1
2
3
4
5
6
7
8
9
10
10 rows selected.
>
The sample data contains employee_id from 100 to 206. The rules have generated (read "updated") rows with employee_id from 1 to 10. Because "return updated rows" is in place the select only returns those rows. Be careful with this as the model actually accesses the table. When using an indexed column the index can be used; otherwise a full table scan is possible.
>
select employee_id
from employees
model
return updated rows
dimension by (employee_id)
measures (0 x)
RULES (
x[for employee_id from 1 to 10 increment 1] = 0
);
EMPLOYEE_ID
-----------
1
2
3
4
5
6
7
8
9
10
10 rows selected.
test@TESTU12>
explain plan for
select employee_id
from employees
model
return updated rows
dimension by (employee_id)
measures (0 x)
RULES (
x[for employee_id from 1 to 10 increment 1] = 0
);
Explained.
test@TESTU12>
select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------
Plan hash value: 1448787533
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 4 | 3 (0)| 00:00:01 |
| 1 | SQL MODEL ORDERED | | 1 | 4 | | |
|* 2 | TABLE ACCESS FULL| EMPLOYEES | 1 | 4 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("EMPLOYEE_ID"<=10 AND "EMPLOYEE_ID">=1)
14 rows selected.
test@TESTU12>
explain plan for
select employee_id
from employees
model
return updated rows
dimension by (employee_id)
measures (0 x)
RULES (
x[for employee_id from 1 to 10 increment 1] = 0
);
Explained.
test@TESTU12>
create index emp_ix on employees (employee_id);
Index created.
test@TESTU12>
select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------
Plan hash value: 1519784151
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 4 | 1 (0)| 00:00:01 |
| 1 | SQL MODEL ORDERED| | 1 | 4 | | |
|* 2 | INDEX RANGE SCAN| EMP_IX | 1 | 4 | 1 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("EMPLOYEE_ID">=1 AND "EMPLOYEE_ID"<=10)
14 rows selected.
test@TESTU12>
>
select criteria from (
select criteria
from dual
model
dimension by (100 criteria)
measures (0 x)
RULES (
x[for criteria from 100 to 105 increment 1] = 0
)
)
where criteria not in (101, 103);
CRITERIA
----------
100
102
104
105
>
Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.
Comments (0)