`

oracle MODEL子句

 
阅读更多

 

转载自:http://blog.csdn.net/wh62592855/article/details/4783021

 

ORACLE 10G中新增的MODEL子句可以用来进行行间计算。MODEL子句允许像访问数组中元素那样访问记录中的某个列。这就提供了诸如电子表格计算之类的计算能力。



1、MODEL子句示例

下面这个查询获取2003年内由员工#21完成的产品类型为#1和#2的销量,并根据2003年的销售数据预测出2004年1月、2月、3月的销量。



select prd_type_id,year,month,sales_amount

from all_sales

where prd_type_id between 1 and 2

and emp_id=21

model

partition by (prd_type_id)

dimension by (month,year)

measures (amount sales_amount)

(

Sales_amount[1,2004]=sales_amount[1,2003],

Sales_amount[2,2004]=sales_amount[2,2003] + sales_amount[3,2003],

Sales_amount[3,2004]=ROUND(sales_amount[3,2003]*1.25,2)

)

Order by prd_type_id,year,month;



现在小分析一下上面这个查询:

partition by (prd_type_id)指定结果是根据prd_type_id分区的。

dimension by (month,year)定义数组的维度是month和year。这就意味着必须提供月份和年份才能访问数组中的单元。

measures (amount sales_amount)表明数组中的每个单元包含一个数量,同时表明数组名为sales_amount。

MEASURES之后的三行命令分别预测2004年1月、2月、3月的销量。

Order by prd_type_id,year,month仅仅是设置整个查询返回结果的顺序。

上面这个查询的输出结果如下:

PRD_TYPE_ID YEAR MONTH SALES_AMOUNT

----------- ---------- ---------- ------------

1 2003 1 10034.84

1 2003 2 15144.65

1 2003 3 20137.83

1 2003 4 25057.45

1 2003 5 17214.56

1 2003 6 15564.64

1 2003 7 12654.84

1 2003 8 17434.82

1 2003 9 19854.57

1 2003 10 21754.19

1 2003 11 13029.73



PRD_TYPE_ID YEAR MONTH SALES_AMOUNT

----------- ---------- ---------- ------------

1 2003 12 10034.84

1 2004 1 10034.84

1 2004 2 35282.48

1 2004 3 25172.29

2 2003 1 1034.84

2 2003 2 1544.65

2 2003 3 2037.83

2 2003 4 2557.45

2 2003 5 1714.56

2 2003 6 1564.64

2 2003 7 1264.84



PRD_TYPE_ID YEAR MONTH SALES_AMOUNT

----------- ---------- ---------- ------------

2 2003 8 1734.82

2 2003 9 1854.57

2 2003 10 2754.19

2 2003 11 1329.73

2 2003 12 1034.84

2 2004 1 1034.84

2 2004 2 3582.48

2 2004 3 2547.29



30 rows selected.



2、用位置标记和符号标记访问数据单元

前面的例子已经介绍了如何使用位置标记来访问数组中的某个单元。还可以使用符号标记显式指定维度的含义。例如,sales_amount[month=1,year=2004]。下面这个查询用符号标记重写了前面的查询。



select prd_type_id,year,month,sales_amount

from all_sales

where prd_type_id between 1 and 2

and emp_id=21

model

partition by (prd_type_id)

dimension by (month,year)

measures (amount sales_amount)

(

Sales_amount[month=1,year=2004]=sales_amount[month=1, year=2003],

Sales_amount[month=2, year=2004]=sales_amount[month=2, year=2003] + sales_amount[month=3, year=2003],

Sales_amount[month=3, year=2004]=ROUND(sales_amount[month=3, year=2003]*1.25,2)

)

Order by prd_type_id,year,month;



使用位置标记或符号标记之间有一个区别需要了解,即它们处理维度中空值的方式不同。例如,sales_amount[null,2003]返回月份为空值、年份为2003的销量,而sales_amount[month=null,year=2004]则不会访问任何有效的数据单元,因为null=null的返回值总是false。



3、用BETWEEN和AND返回特定范围内的数据单元

BETWEEN和AND关键字可用于访问一段范围内的数据单元。例如,下面这个表达式将2004年1月的销量设置为2003年1月至3月销量的平均值取整:

Sales_amount[1,2004]=ROUND(AVG(sales_amount)[month between 1 and 3,2003],2)

下面这个查询展示了上述表达式的用法:

select prd_type_id,year,month,sales_amount

from all_sales

where prd_type_id between 1 and 2

and emp_id=21

model

partition by (prd_type_id)

dimension by (month,year)

measures (amount sales_amount)

(

Sales_amount[1,2004]=ROUND(AVG(sales_amount)[month between 1 and 3,2003],2)

)

Order by prd_type_id,year,month;

结果如下:

PRD_TYPE_ID YEAR MONTH SALES_AMOUNT

----------- ---------- ---------- ------------

1 2003 1 10034.84

1 2003 2 15144.65

1 2003 3 20137.83

1 2003 4 25057.45

1 2003 5 17214.56

1 2003 6 15564.64

1 2003 7 12654.84

1 2003 8 17434.82

1 2003 9 19854.57

1 2003 10 21754.19

1 2003 11 13029.73



PRD_TYPE_ID YEAR MONTH SALES_AMOUNT

----------- ---------- ---------- ------------

1 2003 12 10034.84

1 2004 1 15105.77

2 2003 1 1034.84

2 2003 2 1544.65

2 2003 3 2037.83

2 2003 4 2557.45

2 2003 5 1714.56

2 2003 6 1564.64

2 2003 7 1264.84

2 2003 8 1734.82

2 2003 9 1854.57



PRD_TYPE_ID YEAR MONTH SALES_AMOUNT

----------- ---------- ---------- ------------

2 2003 10 2754.19

2 2003 11 1329.73

2 2003 12 1034.84

2 2004 1 1539.11



26 rows selected.



4、用ANY和IS ANY访问所有的数据单元

可以用ANY和IS ANY谓词访问数组中所有的数据单元。ANY和位置标记合用,IS ANY和符号标记合用。例如,下面这个表达式将2004年1月的销量设置为所有年份月份的销量之和取整:

Sales_amount[1,2004]=ROUND(SUM(sales_amount)[ANY,year IS ANY],2)

下面这个查询展示了上述表达式的用法:

select prd_type_id,year,month,sales_amount

from all_sales

where prd_type_id between 1 and 2

and emp_id=21

model

partition by (prd_type_id)

dimension by (month,year)

measures (amount sales_amount)

(

Sales_amount[1,2004]=ROUND(SUM(sales_amount)[ANY,year IS ANY],2)

)

Order by prd_type_id,year,month;



结果如下:

PRD_TYPE_ID YEAR MONTH SALES_AMOUNT

----------- ---------- ---------- ------------

1 2003 1 10034.84

1 2003 2 15144.65

1 2003 3 20137.83

1 2003 4 25057.45

1 2003 5 17214.56

1 2003 6 15564.64

1 2003 7 12654.84

1 2003 8 17434.82

1 2003 9 19854.57

1 2003 10 21754.19

1 2003 11 13029.73



PRD_TYPE_ID YEAR MONTH SALES_AMOUNT

----------- ---------- ---------- ------------

1 2003 12 10034.84

1 2004 1 197916.96

2 2003 1 1034.84

2 2003 2 1544.65

2 2003 3 2037.83

2 2003 4 2557.45

2 2003 5 1714.56

2 2003 6 1564.64

2 2003 7 1264.84

2 2003 8 1734.82

2 2003 9 1854.57



PRD_TYPE_ID YEAR MONTH SALES_AMOUNT

----------- ---------- ---------- ------------

2 2003 10 2754.19

2 2003 11 1329.73

2 2003 12 1034.84

2 2004 1 20426.96



26 rows selected.



5、用CURRENTV()获取某个维度的当前值

CURRENTV()函数用于获得某个维度的当前值。例如,下面的表达式将2004年第一个月的销量设置为2003年同月销量的1.25倍。注意此处用CURRENTV()获得当前月份,其值为1

Sales_amount[1,2004]=ROUND(sales_amount[CURRENTV(),2003]*1.25,2)

下面这个查询展示了上述表达式的用法:

select prd_type_id,year,month,sales_amount

from all_sales

where prd_type_id between 1 and 2

and emp_id=21

model

partition by (prd_type_id)

dimension by (month,year)

measures (amount sales_amount)

(

Sales_amount[1,2004]=ROUND(sales_amount[CURRENTV(),2003]*1.25,2)

)

Order by prd_type_id,year,month;

运行结果如下:

PRD_TYPE_ID YEAR MONTH SALES_AMOUNT

----------- ---------- ---------- ------------

1 2003 1 10034.84

1 2003 2 15144.65

1 2003 3 20137.83

1 2003 4 25057.45

1 2003 5 17214.56

1 2003 6 15564.64

1 2003 7 12654.84

1 2003 8 17434.82

1 2003 9 19854.57

1 2003 10 21754.19

1 2003 11 13029.73



PRD_TYPE_ID YEAR MONTH SALES_AMOUNT

----------- ---------- ---------- ------------

1 2003 12 10034.84

1 2004 1 12543.55

2 2003 1 1034.84

2 2003 2 1544.65

2 2003 3 2037.83

2 2003 4 2557.45

2 2003 5 1714.56

2 2003 6 1564.64

2 2003 7 1264.84

2 2003 8 1734.82

2 2003 9 1854.57



PRD_TYPE_ID YEAR MONTH SALES_AMOUNT

----------- ---------- ---------- ------------

2 2003 10 2754.19

2 2003 11 1329.73

2 2003 12 1034.84

2 2004 1 1293.55



26 rows selected.



6、用FOR循环访问数据单元

可以通过FOR循环访问数据单元。例如,下面这个表达式将2004年前三个月的销量设置为2003年相应月份销量的1.25倍。注意其中使用了FOR循环,还通过INCREMENT关键字定义每一次循环迭代中month的增量:

Sales_amount[FOR month from 1 TO 3 INCREMENT 1,2004]=

ROUND(sales_amount[CURRENTV(),2003]*1.25,2)

下面这个和查询语句展示了上述表达式的用法:

select prd_type_id,year,month,sales_amount

from all_sales

where prd_type_id between 1 and 2

and emp_id=21

model

partition by (prd_type_id)

dimension by (month,year)

measures (amount sales_amount)

(

Sales_amount[FOR month from 1 TO 3 INCREMENT 1,2004]=

ROUND(sales_amount[CURRENTV(),2003]*1.25,2)

)

Order by prd_type_id,year,month;

运行结果如下:

PRD_TYPE_ID YEAR MONTH SALES_AMOUNT

----------- ---------- ---------- ------------

1 2003 1 10034.84

1 2003 2 15144.65

1 2003 3 20137.83

1 2003 4 25057.45

1 2003 5 17214.56

1 2003 6 15564.64

1 2003 7 12654.84

1 2003 8 17434.82

1 2003 9 19854.57

1 2003 10 21754.19

1 2003 11 13029.73



PRD_TYPE_ID YEAR MONTH SALES_AMOUNT

----------- ---------- ---------- ------------

1 2003 12 10034.84

1 2004 1 12543.55

1 2004 2 18930.81

1 2004 3 25172.29

2 2003 1 1034.84

2 2003 2 1544.65

2 2003 3 2037.83

2 2003 4 2557.45

2 2003 5 1714.56

2 2003 6 1564.64

2 2003 7 1264.84



PRD_TYPE_ID YEAR MONTH SALES_AMOUNT

----------- ---------- ---------- ------------

2 2003 8 1734.82

2 2003 9 1854.57

2 2003 10 2754.19

2 2003 11 1329.73

2 2003 12 1034.84

2 2004 1 1293.55

2 2004 2 1930.81

2 2004 3 2547.29



30 rows selected.



7、处理空值和缺失值

1)使用IS PRESENT

当数据单元指定的记录在MODEL子句执行之前存在,则IS PRESENT返回TRUE。例如:

Sales_amount[CURRENTV(),2003] IS PRESENT

如果Sales_amount[CURRENTV(),2003]存在,则返回TRUE。

下面的表达式将2004年前三个月的销量设置为2003年同期销量的1.25倍:

Sales_amount[FOR month from 1 TO 3 INCREMENT 1,2004]=

CASE WHEN Sales_amount[CURRENTV(),2003] IS PRESENT THEN

ROUND(sales_amount[CURRENTV(),2003]*1.25,2)

ELSE

0

END



下面这个查询展示了上述表达式的用法:

select prd_type_id,year,month,sales_amount

from all_sales

where prd_type_id between 1 and 2

and emp_id=21

model

partition by (prd_type_id)

dimension by (month,year)

measures (amount sales_amount)

(

Sales_amount[FOR month from 1 TO 3 INCREMENT 1,2004]=

CASE WHEN Sales_amount[CURRENTV(),2003] IS PRESENT THEN

ROUND(sales_amount[CURRENTV(),2003]*1.25,2)

ELSE

0

END

)

Order by prd_type_id,year,month;



2)使用PRESENTV()

如果cell引用的记录在MODEL子句执行以前就存在,那么PRESENTV(cell,expr1,expr2)返回表达式expr1。如果这条记录不存在,则返回表达式expr2。例如:

PRESENTV(sales_amount[CURRENTV(),2003],

ROUND(sales_amount[CURRENTV(),2003]*1.25,2),0)

如果sales_amount[CURRENTV(),2003]存在,上面的表达式返回取整后的销量;否则,返回0.下面这个查询展示了上述表达式的用法:

select prd_type_id,year,month,sales_amount

from all_sales

where prd_type_id between 1 and 2

and emp_id=21

model

partition by (prd_type_id)

dimension by (month,year)

measures (amount sales_amount)

(

Sales_amount[FOR month from 1 TO 3 INCREMENT 1,2004]=

PRESENTV(sales_amount[CURRENTV(),2003],

ROUND(sales_amount[CURRENTV(),2003]*1.25,2),0)

)

Order by prd_type_id,year,month;



3)使用PRESENTNNV()

如果cell引用的单元在MODEL子句执行之前已经存在,并且该单元的值不为空,则PRESENTNNV(cell,expr1,expr2)返回表达式expr1。如果记录不存在,或单元值为空值,则返回表达式expr2。例如:

PRESENTNNV(sales_amount[CURRENTV(),2003],

ROUND(sales_amount[CURRENTV(),2003]*1.25,2),0)

如果sales_amount[CURRENTV(),2003]存在且为非空值,那么上面的表达式将返回取整后的销量;否则返回0。



4)使用IGNORE NAV和KEEP NAV

IGNORE NAV的返回值如下:

空值或缺失数字值时返回0。

空值或缺失字符串值时返回空字符串。

空值或缺失日期值时返回01-JAN-2000。

其他所有数据库类型时返回空值。

KEEP NAV对空值或缺失数字值返回空值。注意默认条件下使用KEEP NAV。

下面这个查询展示了IGNORE NAV的用法:

select prd_type_id,year,month,sales_amount

from all_sales

where prd_type_id between 1 and 2

and emp_id=21

model IGNORE NAV

partition by (prd_type_id)

dimension by (month,year)

measures (amount sales_amount)

(

Sales_amount[FOR month from 1 TO 3 INCREMENT 1,2004]=

ROUND(sales_amount[CURRENTV(),2003]*1.25,2)

)

Order by prd_type_id,year,month;



8、更新已有的单元

默认情况下,如果表达式左端的引用单元存在,则更新该单元。如果该单元不存在,就在数组中创建一条新的记录。可以用RULES UPDATE改变这种默认的行为,指出在单元不存在的情况下不创建新纪录。

下面这个查询展示了RULES UPDATE的用法:

select prd_type_id,year,month,sales_amount

from all_sales

where prd_type_id between 1 and 2

and emp_id=21

model IGNORE NAV

partition by (prd_type_id)

dimension by (month,year)

measures (amount sales_amount)

RULES UPDATE

(

Sales_amount[FOR month from 1 TO 3 INCREMENT 1,2004]=

ROUND(sales_amount[CURRENTV(),2003]*1.25,2)

)

Order by prd_type_id,year,month;

运行结果如下:

PRD_TYPE_ID YEAR MONTH SALES_AMOUNT

----------- ---------- ---------- ------------

1 2003 1 10034.84

1 2003 2 15144.65

1 2003 3 20137.83

1 2003 4 25057.45

1 2003 5 17214.56

1 2003 6 15564.64

1 2003 7 12654.84

1 2003 8 17434.82

1 2003 9 19854.57

1 2003 10 21754.19

1 2003 11 13029.73



PRD_TYPE_ID YEAR MONTH SALES_AMOUNT

----------- ---------- ---------- ------------

1 2003 12 10034.84

2 2003 1 1034.84

2 2003 2 1544.65

2 2003 3 2037.83

2 2003 4 2557.45

2 2003 5 1714.56

2 2003 6 1564.64

2 2003 7 1264.84

2 2003 8 1734.82

2 2003 9 1854.57

2 2003 10 2754.19



PRD_TYPE_ID YEAR MONTH SALES_AMOUNT

----------- ---------- ---------- ------------

2 2003 11 1329.73

2 2003 12 1034.84



24 rows selected.



可以看到,虽然2004年的单元不存在,可是同时指定了RULES UPDATE,所以不会在数组中为2004年创建新纪录,因此这条查询语句不会返回2004年的记录。

分享到:
评论

相关推荐

    Oracle中使用SQL MODEL定义行间计算

    Oracle中的SQL MODEL子句是一种强大的工具,用于在数据库内执行复杂的行间计算,它允许用户在不依赖外部应用程序或电子表格的情况下对数据进行高级处理。MODEL子句的主要优点在于其性能提升、可伸缩性和可管理性,...

    《Pro Oracle SQL》CHAPTER 9 The Model Clause -- 9.6 Aggregation

    在Oracle数据库中,Model子句是一种强大的SQL工具,用于处理复杂的建模和计算任务,尤其在数据建模、预测分析以及复杂的数据转换方面表现出色。本章“《Pro Oracle SQL》CHAPTER 9 The Model Clause”重点讲解了...

    《Pro Oracle SQL》CHAPTER 9 The Model Clause -- 9.5 Evaluation Order

    在Oracle SQL中,Model子句是一种高级的行处理工具,用于进行复杂的行计算和模拟迭代过程,比如解决最优化问题或者模拟时间序列分析。本节内容主要涉及Model子句执行时的逻辑流程和数据处理顺序。 Model子句允许...

    《Pro Oracle SQL》CHAPTER 9 The Model Clause -- 9.4Returning Updated Rows

    《Pro Oracle SQL》一书的第9章深入探讨了Oracle数据库中的"Model"子句,这一章节重点关注如何使用Model子句来更新数据行。在Oracle SQL中,Model子句是一种强大的功能,允许进行复杂的行处理和模拟迭代计算,通常...

    《Pro Oracle SQL》CHAPTER 9 -- 9.10Performance Tuning with the Model Clause

    在Oracle数据库中,Model子句是一种强大的功能,它允许数据建模和复杂的计算,尤其适用于解决多步骤计算问题,如模拟、预测和序列生成等。本章节深入探讨了如何利用Model子句来提升SQL查询的执行效率。 Model子句的...

    Oracle中使用SQL MODEL定义行间计算.pdf

    在Oracle数据库10g中,`MODEL`子句提供了一种强大而灵活的方法来执行行间计算,它允许用户根据查询结果定义多维数组,并将规则应用于这些数组以计算新值。与传统方法(如在应用程序或PC电子表格中进行计算)相比,...

    《Pro Oracle SQL》CHAPTER 9 -- 9.2 Inter-Row Referencing via the Model clause

    《Pro Oracle SQL》是Oracle数据库查询的一本权威指南,其中第9章主要讲解了如何使用Model子句进行行间引用,这是一个高级SQL特性,用于处理复杂的行与行之间的计算和逻辑操作。9.2章节专注于Inter-Row Referencing...

    Oracle SQL高级编程

    第9章 Model子句 225 第10章 子查询因子化 254 第11章 半联结和反联结 292 第12章 索引 334 第13章 SELECT以外的内容 360 第14章 事务处理 386 第15章 测试与质量保证 415 第16章 计划稳定性与控制 443

    Oracle SQL高级编程(资深Oracle专家力作,OakTable团队推荐)--随书源代码

    9.10 使用Model子句进行性能调优 243 9.10.1 执行计划 243 9.10.2 谓语前推 246 9.10.3 物化视图 247 9.10.4 并行 249 9.10.5 Model子句执行中的分区 250 9.10.6 索引 251 9.11 子查询因子化 252 9.12 小结...

    oracle行列转换总结

    本文将深入探讨Oracle中实现行列转换的几种方法,包括使用`UNION ALL`、`MODEL`子句以及集合类型(`collections`),并提供具体的示例来帮助理解。 ### 1. 使用`UNION ALL`进行行列转换 `UNION ALL`是一种简单直接的...

    oracle行列转换

    这种操作可以使用 UNION ALL 语句、MODEL 子句和 COLLECTION 语句来实现。 1. 使用 UNION ALL 语句 UNION ALL 语句可以将多个 SELECT 语句的结果合并成一个结果集。 示例代码: ```sql SELECT * FROM T_COL_ROW;...

    Oracle高级sql学习与练习

    18. MODEL语句提供了对表中数据进行基于规则的计算和更新的能力。 19. 10G闪回查询功能允许用户查看或回滚到之前的数据库版本,是数据恢复的重要工具。 20. 行列转换是一个常见的数据处理问题,通过特定的函数和子...

    《Pro Oracle SQL》CHAPTER 9 The Model Clause -- 9.7 Iteration

    《Pro Oracle SQL》一书中的第9章详细探讨了Oracle SQL中的“模型”子句,这一章的主题是“9.7 迭代”。在Oracle数据库中,模型子句是一种强大的功能,它允许用户进行复杂的多步骤计算,尤其适用于处理数组、矩阵...

    Oracle 行列转换总结

    以上介绍了几种常用的行列转换方法,包括使用`UNION ALL`、`MODEL`子句以及`AGGREGATE FUNCTION`等方式。这些方法各有优缺点,在实际应用中可以根据需求选择最合适的方式。需要注意的是,不同Oracle版本支持的功能...

    pro_oracle_sql.pdf(英文版)

    他们共同探讨了Oracle SQL语言的强大特性,包括分析函数、MODEL子句以及高级分组语法,这些都是在报告和商业智能应用中创建高效查询所不可或缺的。 为了掌握Oracle SQL的精髓,读者需要采取一种三管齐下的方法。...

    《Pro Oracle SQL》CHAPTER 9 The Model Clause -- 9.3 Positional and Symbolic Refere

    《Pro Oracle SQL》一书中的第9章详细探讨了Oracle SQL中的“模型”子句,这一章重点关注了位置引用和符号引用的概念。在Oracle数据库中,模型子句是一种强大的工具,用于处理复杂的行列操作,例如数据建模、数据...

    oracle ebs开发文档

    这部分介绍了如何在 EBS 11i 中使用 Model-View-Controller (MVC) 设计模式来开发 Forms,这种模式有助于分离数据、用户界面和控制逻辑,从而提高代码的可维护性和扩展性。 #### 十一、EBS 预警功能自定义 **11.1 ...

Global site tag (gtag.js) - Google Analytics