Oracle的model语句入门-转

Model语句是Oracle 10g的新功能之一。 本文通过一些简单的例子帮助理解Model语句的用法,复杂使用场景请参考其他文章。

环境:当然需要Oracle 10g以上,本人是在11g上测试的。

1. 什么是model语句

 model语句是Oracle10g的新功能,可以在select语句里面像其他编程语言操作数组一样,对SQL的结果集进行处理。执行顺序是位于Having之后。

select的解析执行顺序

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语句

model的好处

 Oracle 9i为止,需要使用各种计算分析函数,union all等,以及借助其他开发语言(C#及Java等)进行复杂计算统计合并等。使用Model之后,这些都可以在SQL里面进行了。

 model典型使用场景

  1. 合计行追加
  2. 行列变换
  3. 使用当前行的前后行
  4. RegExp_Replace函数的循环执行

2. HelloWorld

 先看一个简单的例子。

例句1

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

说明:

model model语句的关键字,必须

dimension by dimension维度的意思,可以理解为数组的索引,必须

measures 指定作为数组的列

rules 对数组进行各种操作的描述。

例句1的理解:

 select ‘abcdefghijklmn‘ as ArrValue, 
1 as soeji from dual;

上面子查询的结果:

ArrValue       soeji

   
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‘);

执行结果:

ArrValue       soeji

   
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‘);

结果是:

ArrValue       soeji

   
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‘);

结果是:

ArrValue       soeji

   
Hello CodeZine 4

 使用model return updated rows的话,被rules更新或者插入的行才显示,没有更新过的行不再作为SQL的结果。

再来一个,有下表,希望在检索结果后面加一个合计行:

addTotal

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的话可以使用rollupunion all等实现

rollup方式:

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行
时间: 2024-08-29 20:49:49

Oracle的model语句入门-转的相关文章

通过案例学调优之--Oracle Time Model(时间模型)

通过案例学调优之--Oracle Time Model(时间模型) 数据库时间  优化不仅仅是缩短等待时间.优化旨在缩短最终用户响应时间和(或)尽可能减少每个请求占用的平均资源.有时这些目标可同时实现,而有时则需要进行折衷(如在并行查询时).通常可以认为,优化就是避免以浪费的方式占用或保留资源. 对数据库发出的任何请求都由两个不同的段组成:等待时间(数据库等待时间)和服务时间(数据库 CPU 时间).等待时间是各种数据库实例资源的所有等待时间的总和.CPU 时间是实际处理请求时消耗的时间的总和.

新手Oracle安装及使用入门

新手Oracle安装及使用入门 一.安装Oracle Step1 下载oracle压缩包并解压到同一文件夹下面 Step2 双击setup.exe进行安装 Step3:进入如下界面配置: 邮箱可不填,去掉更新 除了设置密码,其他均可默认安装! 可自行选择安装路径,确保该安装盘有4G以上内存可使用就行. 若检测有问题就选择“全部忽略” 完成之后接着进行数据库创建(wait for long~~): 可按照以上在浏览器输入该url进行登录并管理服务端,登录成功见如下界面(此步骤也可以跳过不操作):

oracle学习--循环语句

oracle学习--循环语句  loop循环: create or replace procedure pro_test_loop is i number; begin i:=0; loop i:=i+1; dbms_output.put_line(i); if i>5 then exit; end if; end loop; end pro_test_loop; while循环: create or replace procedure pro_test_while is i number; b

1.SQL语句入门

--SQL语句入门-- --1.sql语言是解释语言 --2.它不区分大小写 --3.没有“”,所有字符或者字符串都使用''包含 --4.sql里面也有类似于c#的运算符 -- 算术运算符:+ - * / % -- 关系运算符:> < >= <= =(赋值与逻辑相等都是=), <> != -- 逻辑运算符:!(not)&&(and) || (or) --5.在sql中没有BOOL值的概念,也就意味着条件中不能写true/false 但是对于bit类型的值

Oracle分页查询语句的写法(转)

分页查询是我们在使用数据库系统时经常要使用到的,下文对Oracle数据库系统中的分页查询语句作了详细的介绍,供您参考. Oracle分页查询语句使我们最常用的语句之一,下面就为您介绍的Oracle分页查询语句的用法,如果您对此方面感兴趣的话,不妨一看. Oracle分页查询语句基本上可以按照本文给出的格式来进行套用.Oracle分分页查询格式: SELECT * FROM ( SELECT A.*, ROWNUM RN FROM (SELECT * FROM TABLE_NAME) A WHER

Oracle 动态SQL语句

Oracle 动态SQL语句 (2012-06-18 16:36:12) 转载▼ 标签: oracle it   EXECUTE IMMEDIATE代替了以前Oracle8i中DBMS_SQLpackage包. 它解析并马上执行动态的SQL语句或非运行时创建的PL/SQL块.动态创建和执行SQL语句性能超前,EXECUTEIMMEDIATE的目标在于减小企业费用并获得较高的性能,较之以前它相当容易编码.尽管DBMS_SQL仍然可用,但是推荐使用EXECUTEIMMEDIATE,因为它获的收益在包

Oracle之sql语句优化

项目中虽然使用了orm映射,但Oracle系统的优化还是很有价值的,这里从sql语句的角度对常用的语句做下总结. 1.from字段中的优化: Oracle安照从右到左的顺序加载表数据,应该把可以排除数据最多的表放到后面(基础表). 比如,在关联查询中,把课程表放到后面,成绩表放到前面,因为课程表数据一般比较少,关联的时候可以快速的过滤掉一些成绩数据. 2.where中的优化: 对可以过滤数据最多的,放到后面,原理也是Oracle执行从下到上(从右到左)的顺序. 3.使用列名替代*: 省去从字典表

Oracle安装及使用入门

新手Oracle安装及使用入门 一.安装Oracle Step1 下载oracle压缩包并解压到同一文件夹下面 Step2 双击setup.exe进行安装 Step3:进入如下界面配置: 邮箱可不填,去掉更新 除了设置密码,其他均可默认安装! 可自行选择安装路径,确保该安装盘有4G以上内存可使用就行. 若检测有问题就选择“全部忽略” 完成之后接着进行数据库创建(wait for long~~): 可按照以上在浏览器输入该url进行登录并管理服务端,登录成功见如下界面(此步骤也可以跳过不操作):

oracle常用SQL语句(汇总版)

Oracle数据库常用sql语句 ORACLE 常用的SQL语法和数据对象 一.数据控制语句 (DML) 部分 1.INSERT (往数据表里插入记录的语句) INSERT INTO 表名(字段名1, 字段名2, ……) VALUES ( 值1, 值2, ……); INSERT INTO 表名(字段名1, 字段名2, ……) SELECT (字段名1, 字段名2, ……) FROM 另外的表名; 字符串类型的字段值必须用单引号括起来, 例如: ’GOOD DAY’ 如果字段值里包含单引号’ 需要