Model語句是Oracle 10g的新功能之一。 本文經過一些簡單的例子幫助理解Model語句的用法,複雜使用場景請參考其餘文章。編程
環境:固然須要Oracle 10g以上,本人是在11g上測試的。數組
model語句是Oracle10g的新功能,能夠在select語句裏面像其餘編程語言操做數組同樣,對SQL的結果集進行處理。執行順序是位於Having以後。
編程語言
1. from語句
2. where語句 (結合條件)
3. start with語句
4. connect by語句
5. where語句
6. group by語句
7. having語句
8. model語句
9. select語句
10. union、minus、intersect等集合演算演算
11. order by語句
Oracle 9i爲止,須要使用各類計算分析函數,union all等,以及藉助其餘
開發語言(C#及Java等)進行復雜計算統計合併等。使用Model以後,這些均可以在SQL裏面進行了。函數
model典型使用場景
。測試
RegExp_Replace函數的循環執行
先看一個簡單的例子。spa
select ArrValue,soeji
from (select 'abcdefghijklmn' as ArrValue, 1 as soeji from dual)
model
dimension by(soeji)
measures(ArrValue)
rules(ArrValue[1] = 'Hello World');
ArrValue | soeji |
Hello World | 1 |
說明:code
model語句的關鍵字,必須
。dimension維度的意思,能夠理解爲數組的索引,必須
。rules 對數組進行各類操做的描述。索引
例句1的理解:開發
select 'abcdefghijklmn' as ArrValue,
1 as soeji from dual;rem
abcdefghijklmn | 1 |
根據下面語句
model
dimension by (soeji)
measures(ArrValue)
soeji做爲索引對數組ArrValue進行操做,rules(ArrValue[1] = 'Hello World')就是說
用Hello World覆蓋ArrValue[1]裏面的值。
在看一個例子,例句2:
select ArrValue,soeji
from (select 'abcdefghijklmn' as ArrValue,
1 as soeji from dual)
model
dimension by(soeji)
measures(ArrValue)
rules(ArrValue[1] = 'Hello World',
ArrValue[2] = 'Hello model');
Hello World | 1 |
Hello model | 2 |
rules的缺省行爲是存在就更新,不存在則追加
,所以,ArrValue[1] = 'Hello World'是更新一條,
ArrValue[2] = 'Hello Model'
insert一條。
再看一個例子,例句3:
select ArrValue,soeji from (select 'abcdefghijklmn' as ArrValue, 1 assoeji from dual) model dimension by(soeji) measures(ArrValue) rules(ArrValue[3] ='Hello Oracle');
abcdefghijklmn | 1 |
Hello Oracle | 3 |
model語句裏面,索引能夠是不連續的。
再看一個例子,例句4:
select ArrValue,soeji from (select 'abcdefghijklmn' as ArrValue, 1 assoeji from dual) model return updated rows dimension by(soeji) measures(ArrValue) rules(ArrValue[4] = 'Hello CodeZine');
Hello CodeZine | 4 |
使用model return updated rows的話,被
rules
更新或者插入的行才顯示,沒有更新過的行再也不做爲SQL的結果。
ID | Val |
1 | 30 |
2 | 100 |
3 | 50 |
4 | 300 |
select ID,Val
from addTotal
model
dimension by(ID)
measures(Val)
rules( Val[null] = Val[1]+Val[2]+Val[3]+Val[4] );
ID | Val |
1 | 30 |
2 | 100 |
3 | 50 |
4 | 300 |
null | 480 |
不使用model的話能夠使用
rollup
,union all等實現
。
select ID,sum(Val) as Val from addTotal group by rollup(ID);
union all方式:
select ID,Val from addTotal union all select null,Sum(Val) from addTotal;
=================================================
以產品產量表爲例,一個工廠(用code表示)生產多種產品(用p_id表示),每種產品具備生產量(v1)和銷售量(v2)
產品代碼具備審覈關係,好比’10’=’30’+’31’,其中’10’表明大類,’30’和’31’表明’10’大類下的小類。
SQL> create table t603 (code varchar(10),p_id varchar(7),v1 number(10),v2 number(10));
Table created.
SQL> insert into t603 values(’600001’,’30’,1,1);
SQL> insert into t603 values(’600001’,’31’,1,1);
SQL> insert into t603 values(’600001’,’10’,2,2);
SQL> insert into t603 values(’600002’,’10’,3,2);
SQL> insert into t603 values(’600002’,’31’,2,1);
SQL> insert into t603 values(’600002’,’30’,2,1);
SQL> commit;
Commit complete.
SQL> select * from t603;
CODE P_ID V1 V2
600001 30 1 1
600001 31 1 1
600001 10 2 2
600002 10 3 2
600002 31 2 1
600002 30 2 1
6 rows selected.
SELECT code,
p_id, v1
FROM t603
WHERE code IN (’600001’,’600002’)
MODEL RETURN UPDATED ROWS
PARTITION BY (code)
DIMENSION BY (p_id)
MEASURES (v1)
RULES (
v1[’err1’] = v1[’30’] + v1[’31’] -v1[’10’])
ORDER BY code, p_id;
其中rule表示計算規則,’err1’表示這條審覈關係的代號,它的值等於P_ID爲’30’的v1值+P_ID爲’31’的v1值-P_ID爲’10’的v1值
PARTITION BY (code)表示按工廠分區,即審覈在一個工廠內的產品
MODEL 關鍵字後面的 RETURN UPDATED ROWS 子句將結果限制爲在該查詢中建立或更新的那些行。使用該子句是使結果集只包含新計算的值,在本例中就是審覈結果
CODE P_ID V1
600001 err1 0
600002 err1 1
若是返回值=0,表示v1[’30’] + v1[’31’] =v1[’10’]審覈經過,不然,審覈不經過
SELECT code,
p_id, v1,v2
FROM t603
WHERE code IN (’600001’,’600002’)
MODEL RETURN UPDATED ROWS
PARTITION BY (code)
DIMENSION BY (p_id)
MEASURES (v1,v2)
RULES (
v1[’err1’] = v1[’30’] + v1[’31’] -v1[’10’],
v2[’err1’] = v2[’30’] + v2[’31’] -v2[’10’])
ORDER BY code, p_id;
CODE P_ID V1 V2
600001 err1 0 0
600002 err1 1 0
若是表格中包含多個維度的數據,好比時間,多個維度均可以編寫規則,好比2008年的審覈關係
SELECT year,code,
p_id, v1
FROM t603_1
WHERE code IN (’600001’,’600002’)
MODEL RETURN UPDATED ROWS
PARTITION BY (code)
DIMENSION BY (p_id,year)
MEASURES (v1)
RULES (
v1[’err1’,2008] = v1[’30’,2008] + v1[’31’,2008] -v1[’10’,2008])
ORDER BY code, p_id;
YEAR CODE P_ID V1
2008 600001 err1 0
2008 600002 err1 1
若是維度不影響規則,也能夠只分區,而沿用原來的規則
SELECT year,code,
p_id, v1
FROM t603_1
WHERE code IN (’600001’,’600002’)
MODEL RETURN UPDATED ROWS
PARTITION BY (code,year)
DIMENSION BY (p_id)
MEASURES (v1)
RULES (
v1[’err1’] = v1[’30’] + v1[’31’] -v1[’10’])
ORDER BY code, p_id;
YEAR CODE P_ID V1
2008 600001 err1 0
2008 600002 err1 1
SQL> create table t603_2 as select * from t603_1;
Table created.
SQL> insert into t603_2 select ’2007’ year,code,p_id,v1,v2 from t603_1;
6 rows created.
若是表中具備多個年份的數據,每一個年份的審覈結果都能顯示 SELECT year,code, p_id, v1 FROM t603_2 WHERE code IN (’600001’,’600002’) MODEL RETURN UPDATED ROWS PARTITION BY (code,year) DIMENSION BY (p_id) MEASURES (v1) RULES ( v1[’err1’] = v1[’30’] + v1[’31’] -v1[’10’]) ORDER BY code, p_id; YEAR CODE P_ID V1 2008 600001 err1 0 2007 600001 err1 0 2007 600002 err1 1 2008 600002 err1 1 規則也能夠是多個維度不一樣取值,本例假定不一樣年份之間比較,好比要求2008年的’10’=2007年的’30’+’31’ SELECT year,code, p_id, v1 FROM t603_2 WHERE code IN (’600001’,’600002’) MODEL RETURN UPDATED ROWS PARTITION BY (code) DIMENSION BY (p_id,year) MEASURES (v1) RULES ( v1[’err1’,2008] = v1[’30’,2007] + v1[’31’,2007] -v1[’10’,2008]) ORDER BY code, p_id; YEAR CODE P_ID V1 2008 600001 err1 0 2008 600002 err1 1 若是年份不少,每一個年份都是和上年比較,這種描述能夠用CV()函數簡化 SQL> insert into t603_2 select ’2006’ year,code,p_id,v1,v2 from t603_1; SELECT year,code, p_id, v1 FROM t603_2 WHERE code IN (’600001’,’600002’) MODEL RETURN UPDATED ROWS PARTITION BY (code) DIMENSION BY (p_id,year) MEASURES (v1) RULES ( v1[’err1’,for year in( 2007 ,2008)] = v1[’30’,CV(year)-1] + v1[’31’,CV(year)-1] -v1[’10’,CV(year)]) ORDER BY code, p_id; YEAR CODE P_ID V1 2007 600001 err1 0 2008 600001 err1 0 2007 600002 err1 1 2008 600002 err1 1 若是year是數值類型,還能夠用for year from 2007 to 2009 increment 1的語法,若是是其餘類型,還能夠用在in子句帶子查詢的辦法, 好比for year in (select year from t603_2)。 但須要注意不能採用year in 的語法,year in的語法只能符號引用已經存在的單元格,而v1[’err1’,x]是新單元格。 單個年份的寫法以下: SELECT year,code, p_id, v1 FROM t603_2 WHERE code IN (’600001’,’600002’) MODEL RETURN UPDATED ROWS PARTITION BY (code) DIMENSION BY (p_id,year) MEASURES (v1) RULES ( v1[’err1’,2008] = v1[’30’,CV()] + v1[’31’,CV()] -v1[’10’,CV()]) ORDER BY code, p_id; YEAR CODE P_ID V1 2008 600001 err1 0 2008 600002 err1 1 而 SELECT year,code, p_id, v1 FROM t603_2 WHERE code IN (’600001’,’600002’) MODEL RETURN UPDATED ROWS PARTITION BY (code) DIMENSION BY (p_id,year) MEASURES (v1) RULES ( v1[’err1’,year in (’2008’)] = v1[’30’,CV()] + v1[’31’,CV()] -v1[’10’,CV()]) 則返回0行