利用Oracle 10g 的MODEL SQL 進行行間計算

以產品產量表為例,一個工廠(用code 表示)生產多種產品(用p_id 表示),每種產品具有生產量(v1)和銷售量(v2)產品代碼具有審核關係,如’10’=’30’+’31’,其中’10’代表大類,’30’和’31’代表’10’大類下的小類。
SQL>createtablet603(codevarchar(10),p_idvarchar(7),v1number(10),v2number(1
0));
Tablecreated.
SQL>insertintot603values(‘600001′,’30’,1,1);
SQL>insertintot603values(‘600001′,’31’,1,1);
SQL>insertintot603values(‘600001′,’10’,2,2);
SQL>insertintot603values(‘600002′,’10’,3,2);
SQL>insertintot603values(‘600002′,’31’,2,1);
SQL>insertintot603values(‘600002′,’30’,2,1);
SQL>commit;
Commitcomplete.
SQL>select*fromt603;
CODEP_IDV1V2
————————————-
6000013011
6000013111

6000011022
6000021032
6000023121
6000023021
6rowsselected.
SELECTcode,
p_id,v1
FROMt603
WHEREcodeIN(‘600001′,’600002’)
MODELRETURNUPDATEDROWS
PARTITIONBY(code)
DIMENSIONBY(p_id)
MEASURES(v1)
RULES(
v1[‘err1′]=v1[’30’]+v1[’31’]-v1[’10’])
ORDERBYcode,p_id;
其中rule 表示計算規則,’err1’表示這條審核關係的代號,它的值等於P_ID 為’30’的v1 值+P_ID 為’31’的v1 值-P_ID 為’10’的v1 值PARTITION BY (code)表示按工廠分區,即審核在一個工廠內的產品MODEL 關鍵字後面的RETURN UPDATED ROWS 子句將結果限制為在該查詢中創建或更新的那些行。使用該子句是使結果集只包含新計算的值,在本例中就是審核結果

CODEP_IDV1
—————————
600001err10
600002err11
如果返回值=0,表示v1[’30’] + v1[’31’] =v1[’10’]審核通過,否則,審核不通過


SELECTcode,
p_id,v1,v2
FROMt603
WHEREcodeIN(‘600001′,’600002’)
MODELRETURNUPDATEDROWS
PARTITIONBY(code)
DIMENSIONBY(p_id)
MEASURES(v1,v2)
RULES(
v1[‘err1′]=v1[’30’]+v1[’31’]-v1[’10’],
v2[‘err1′]=v2[’30’]+v2[’31’]-v2[’10’])
ORDERBYcode,p_id;
CODEP_IDV1V2
————————————-
600001err100

600002err110
如果表格中包含多個維度的數據,比如時間,多個維度都可以編寫規則,比如2008 年的
審核關係
SELECTyear,code,
p_id,v1
FROMt603_1
WHEREcodeIN(‘600001′,’600002’)
MODELRETURNUPDATEDROWS
PARTITIONBY(code)
DIMENSIONBY(p_id,year)
MEASURES(v1)
RULES(
v1[‘err1′,2008]=v1[’30’,2008]+v1[’31’,2008]-v1[’10’,2008])
ORDERBYcode,p_id;
YEARCODEP_IDV1
——————————-
2008600001err10
2008600002err11
如果維度不影響規則,也可以只分區,而沿用原來的規則
規則也可以是多個維度不同取值,本例假定不同年份之間比較,比如要求2008 年的’1

0’=2007 年的’30’+’31’
SELECTyear,code,
p_id,v1
FROMt603_2
WHEREcodeIN(‘600001′,’600002’)
MODELRETURNUPDATEDROWS
PARTITIONBY(code)
DIMENSIONBY(p_id,year)
MEASURES(v1)
RULES(
v1[‘err1′,2008]=v1[’30’,2007]+v1[’31’,2007]-v1[’10’,2008])
ORDERBYcode,p_id;
YEARCODEP_IDV1
——————————-
2008600001err10
2008600002err11
如果年份很多,每個年份都是和上年比較,這種描述可以用CV()函數簡化
SQL>insertintot603_2select’2006’year,code,p_id,v1,v2fromt603_1;
SELECTyear,code,
p_id,v1

FROMt603_2
WHEREcodeIN(‘600001′,’600002’)
MODELRETURNUPDATEDROWS
PARTITIONBY(code)
DIMENSIONBY(p_id,year)
MEASURES(v1)
RULES(
v1[‘err1′,foryearin(2007,2008)]=v1[’30’,CV(year)-1]+v1[’31’,CV(year)-1]-v1[’10’,CV( y
ear)])
ORDERBYcode,p_id;
YEARCODEP_IDV1
——————————-
2007600001err10
2008600001err10
2007600002err11
2008600002err11
如果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]是新單元格。

單個年份的寫法如下:
SELECTyear,code,
p_id,v1
FROMt603_2
WHEREcodeIN(‘600001′,’600002’)
MODELRETURNUPDATEDROWS
PARTITIONBY(code)
DIMENSIONBY(p_id,year)
MEASURES(v1)
RULES(
v1[‘err1′,2008]=v1[’30’,CV()]+v1[’31’,CV()]-v1[’10’,CV()])
ORDERBYcode,p_id;
YEARCODEP_IDV1
——————————-
2008600001err10
2008600002err11

SELECTyear,code,
p_id,v1
FROMt603_2

WHEREcodeIN(‘600001′,’600002’)
MODELRETURNUPDATEDROWS
PARTITIONBY(code)
DIMENSIONBY(p_id,year)
MEASURES(v1)
RULES(
v1[‘err1’,yearin(‘2008′)]=v1[’30’,CV()]+v1[’31’,CV()]-v1[’10’,CV()])
則返回0 行

This entry was posted in 10G, Oracle.

Comments are closed.

在线客服系统