学院首页 软件应用 编程开发 创意设计 认证培训 软件论坛
ASP ASP.NET PHP JSP SQL MYSQL Java VB

您的位置:学院 >> 编程开发 >> SQL >> Oracle中使用SQL MODEL定义行间计算


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


目的

在本教程中,您将学习如何使用 Oracle 数据库 10g SQL MODEL 子句执行行间计算。

所需时间

大约 30 分钟

主题

本教程包括下列主题:

概述

情景

前提条件

设置示例数据

查看示例语法

使用位置和符号单元格引用

在规则右侧使用多单元格引用

使用 CV() 函数和 ANY 通配符

Coding FOR Loops:指定新单元格的简洁方法

了解规则的评估顺序

处理 NULL 度量和缺失单元格

创建引用模型

创建迭代模型

使用排序规则

总结

概述

利用 SQL MODEL 子句,您可以根据查询结果定义多维数组,然后将规则应用于该数组以计算新值。这些规则可以是复杂的相互依赖的计算。与外部解决方案相比,通过将高级计算集成到数据库中,可以大幅度提升性能、可伸缩性以及可管理性。用户可以将数据保留在 Oracle 环境内,而无需将数据复制到单独的应用程序或 PC 电子表格中。

MODEL 子句通过将查询列映射到以下三组来定义多维数组:分区列、维度列和度量列。这些元素执行以下任务:

分区以类似于分析函数的分区方式(在数据仓库指南中标题为“数据仓库中用于分析的 SQL”的一章中有述)来定义结果集的逻辑块。将 MODEL 规则应用于每个分区的单元格。

维度用于标识分区内的每个度量单元格。这些列用于标识日期、区域以及产品名之类的特征。

度量类似于星型模式中事实表的度量。它们通常包含数值,例如销售单位或成本。通过指定每个单元格的完整维度组合,可以在单元格所处的分区内对其进行访问。

要针对这些多维数组创建规则,您需要定义以维度值形式表达的计算规则。规则灵活且简洁,并且可以使用通配符和 FOR 循环,以最大限度地表达您的意图。利用 MODEL 子句构建的计算通过将分析集成到数据库中改善了传统的电子表格计算,通过符号引用提高了可读性,并提供了可伸缩性和更好的可管理性。

下图使用假设的销售表格从概念的角度概述了该模型的特征。该表格具有四列:国家/地区、产品、年份和销售量。该图分为三个部分。上段阐释了将表格划分为分区、维和度量三列的概念。中段给出了两个假想规则,以预测 Prod1 和 Prod2 的销售,因为产品销售的计算值来自前两年。最后,第三部分显示了将规则应用于这个包含假设数据的表格后得出的查询输出。黑色输出是从数据库检索的数据,而蓝色输出表示根据规则计算出的行。请注意,这些规则是在每个分区内应用的。

映射到分区、维和度量的列

COUNTRY  PRODUCT  YEAR  SALES 
 分区  维度  维度  度量 

规则: sales('prod1', 2002) = sales('prod1', 2000) + sales('prod1', 2001)
sales('prod2', 2002) = sales('prod2', 2000) + sales('prod2', 2001)

MODEL 子句的输出:

COUNTRY  PRODUCT  YEAR  SALES 
 分区  维度  维度  度量 
 A  prod1  2000  10 
 A  prod1  2001  15 
 A  prod2  2000  12 
 A  prod2  2001  16 
 B  prod1  2000  21 
 B  prod1  2001  23 
 B  prod2  2000  28 
 B  prod2  2001  29 
 A  prod1  2002  25 
 A  prod2  2002  28 
 B  prod1  2002  44 
 B  prod2  2002  57

请注意,MODEL 子句没有更新表格中的现有数据,也没有向表格中插入新数据 要更改表格中的值,必须将模型结果提供给 INSERT、UPDATE 或 MERGE 语句。

案例

通过使用 MODEL 子句,您可以将电子表格计算引入数据库。您将使用 Sales History 模式数据并通过包含新 MODEL 子句的 SELECT 语句来执行类似电子表格的计算。您需要标识规则,以找出诸如销售预测之类的信息。

前提条件

开始本教程之前,您应该:

1.完成了教程在 Windows 上安装 Oracle 数据库 10g。

2.下载 model_clause.zip 并将其解压缩到您的工作目录(例如,c:\wkdir)

设置示例数据

使用 SH 模式创建视图。该视图将按国家/地区提供产品销售的年度总计(总款和总量),并跨所有渠道进行聚集。

1.启动一个 SQL*Plus 会话。选择开始 > 程序 > Oracle-OraDB10g_home > Application Development > SQL Plus。

(注意:本教程假设您拥有 c:\wkdir 文件夹。如果没有,则需要创建此文件夹,并将 model_clause.zip 的内容解压缩到此文件夹中。当执行这些脚本时,指定路径)

2.以 SH 用户的身份登录。输入 SH 作为 User Name,并输入 SH 作为 Password。然后单击 OK。

3.首先,确保环境简洁。从 SQL*Plus 会话运行 cleanup.sql 脚本。 @c:\wkdir\cleanup.sql

cleanup.sql 脚本包含以下内容: DROP VIEW sales_view;DROP TABLE dollar_conv;DROP TABLE growth_rate;DROP TABLE ledger;

4.现在,您可以创建 SALES_VIEW 视图。从 SQL*Plus 会话中,执行以下脚本:













@c:\wkdir\sample_data.sql 
sample_data.sql 脚本包含以下内容: CREATE VIEW sales_view AS
SELECT country_name country, prod_name prod, calendar_year year,
SUM(amount_sold) sale, COUNT(amount_sold) cnt
FROM sales, times, customers, countries, products
WHERE sales.time_id = times.time_id AND
sales.prod_id = products.prod_id 
AND sales.cust_id = customers.cust_id
AND customers.country_id = countries.country_id
GROUP BY country_name, prod_name, calendar_year
/

5.验证视图创建正确,并具有 3219 行。从 SQL*Plus 会话中,执行以下脚本:

@c:\wkdir\sel_sv.sql 

sel_sv.sql 脚本包含以下内容: SELECT COUNT(*) FROM sales_view;

6.要使性能最佳化,系统应当已经具有基于以上视图使用的数据构建的物化视图。该物化视图是在 SH 模式数据的安装期间创建的。Oracle 的摘要管理系统将使用上述视图自动重写所有查询,以便利用该物化视图。

查看示例语法

作为模型的初始示例,请考虑以下语句:

SELECT SUBSTR(country,1,20) country, 
   SUBSTR(prod,1,15) prod, year, sales
FROM sales_view
WHERE country IN ('Italy','Japan')
   MODEL RETURN UPDATED ROWS
     PARTITION BY (country) 
     DIMENSION BY (prod, year)
     MEASURES (sale sales)
     RULES (
       sales['Bounce', 2002] = sales['Bounce', 2001] + sales['Bounce', 2000],
       sales['Y Box', 2002] = sales['Y Box', 2001],
       sales['2_Products', 2002] = sales['Bounce', 2002] + sales['Y Box', 2002])
ORDER BY country, prod, year;

结果是:

COUNTRY              PROD                 YEAR       SALES
-------------------- --------------- ---------- ----------
Italy                2_Products            2002   90387.54
Italy                Bounce                2002    9179.99
Italy                Y Box                 2002   81207.55
Japan                2_Products            2002  101071.96
Japan                Bounce                2002   11437.13
Japan                Y Box                 2002   89634.83

因为该语句按照国家/地区划分,所以这些规则一次应用于一个国家/地区的数据。请注意,数据结束于 2001 年,因此为 2002 年或之后年份定义值的任何规则都将插入新单元格。第一个规则将 2002 年 Bounce 的销售定义为 2000 年和 2001 年的销售总和。第二个规则将 2002 年 Y Box 的销售定义为 2001 年的销售值。第三个规则定义了一个名为 2_Products 的类别,它是 2002 年的 Bounce 与 Y Box 值相加所得的总和。请注意,2_Products 的值派生自前两个规则的结果,因此这两个规则必须在 2_Products 规则之前执行。

语法准则

请注意,MODEL 关键字后面的 RETURN UPDATED ROWS 子句将结果限制为在该查询中创建或更新的那些行。使用该子句是使结果集只包含新计算的值的简便方法。在整个示例中,都将用到 RETURN UPDATED ROWS 子句。

示例中显示在规则开头处的 RULES 关键字是可选的,但是建议您使用以方便阅读。

许多示例在 COUNTRY 列并不需要 ORDER BY。但是,为了方便修改示例并添加多个国家/地区,应将其包含在规范中。

技术细节

以下示例演示了 MODEL 子句的主要功能,从基本单元格引用到引用模型以及迭代模型。

使用位置和符号单元格引用

本部分探究了在 MODEL 语句中使用符号和位置单元格引用的技巧。

1.要查看产品 Bounce 于 2000 年在意大利的 SALES 值,并将其设为 10,可使用“位置单元格引用”。单元格引用的值将根据其在表达式中的位置与相应的维度匹配。模型的 DIMENSION BY 子句决定指定给每个维 — 在本例中,第一个位置是产品 (PROD),第二个位置是 YEAR.从 SQL*Plus 会话中,执行以下脚本:

@c:\wkdir\pos_cell1.sql 
pos_cell1.sql 脚本包含以下内容: COLUMN country FORMAT a20
COLUMN prod FORMAT a20

SELECT SUBSTR(country,1,20) country, 
  SUBSTR(prod,1,15) prod, year, sales
FROM sales_view
WHERE country='Italy'
MODEL RETURN UPDATED ROWS
  PARTITION BY (country) 
  DIMENSION BY (prod, year)
  MEASURES (sale sales)
  RULES (
  sales['Bounce', 2000] = 10 )
ORDER BY country, prod, year
/

2.要创建产品 Bounce 于 2005 年在意大利的 SALES 预测值,并将其设为 20,可使用 SELECT 语句中的规则将年份值设为 2005,从而在数组中创建新单元格。从 SQL*Plus 会话中,执行以下脚本:

@c:\wkdir\pos_cell2.sql 
pos_cell2.sql 脚本包含以下内容: SELECT SUBSTR(country,1,20) country, 
  SUBSTR(prod,1,15) prod, year, sales
FROM sales_view
WHERE country='Italy'
MODEL RETURN UPDATED ROWS
  PARTITION BY (country) 
  DIMENSION BY (prod, year)
  MEASURES (sale sales)
  RULES (
  sales['Bounce', 2005] = 20 )
ORDER BY country, prod, year
/

注意:如果您希望创建新单元格(例如,未来几年的值),则必须使用位置引用或 FOR 循环(本教程稍后讨论)。也就是说,位置引用允许更新数组以及向数组中插入新值。这称为 UPSERT 过程,它由 Oracle SQL MERGE 语句处理。

3.要更新产品 Bounce 自 1999 年以来针对意大利记录的所有年份的 SALES,并将它们设为 10,可以使用“符号单元格引用”。单元格引用的值通过布尔条件与相应的维度匹配。您可以使用所有常见的运算符,例如 <、>、IN 和 BETWEEN。在本例中,查询将查找等于 Bounce 的产品值和所有大于 1999 的年份值。这展示了单一规则如何访问多个单元格。从 SQL*Plus 会话中,执行以下脚本:

@c:\wkdir\sym_cell1.sql 

sym_cell1.sql 脚本包含以下内容: SELECT SUBSTR(country,1,20) country, 
SUBSTR(prod,1,15) prod, year, sales
FROM sales_view
WHERE country='Italy'
MODEL RETURN UPDATED ROWS
   PARTITION BY (country) 
   DIMENSION BY (prod, year)
   MEASURES (sale sales)
   RULES (
   sales[prod='Bounce', year>1999] = 10 )
ORDER BY country, prod, year
/

注意:符号引用功能强大,但它们只能用于更新现有的单元格:它们不能创建新单元格,例如,未来几年的销售规划。

4.您希望通过单一查询来更新多个国家/地区的多种产品在数年中的销售,并且还希望插入新的单元格。通过将数个规则置于一个查询中,处理会更加高效,因为这减少了需要访问数据的次数。它还允许使用更为简洁的 SQL,以使开发人员的工作效率更高。从 SQL*Plus 会话中,执行以下脚本:








@c:\wkdir\pos_sym.sql 

pos_sym.sql 脚本包含以下内容: SELECT SUBSTR(country,1,20) country, 
SUBSTR(prod,1,15) prod, year, sales
FROM sales_view WHERE country IN ('Italy','Japan') 
MODEL RETURN UPDATED ROWS
   PARTITION BY (country) 
   DIMENSION BY (prod, year)
   MEASURES (sale sales)
   RULES ( 
   sales['Bounce', 2002] = sales['Bounce', year = 2001] , 
   --positional notation: can insert new cell
   sales['Y Box', year>2000] = sales['Y Box', 1999], 
   --symbolic notation: can update existing cell
   sales['2_Products', 2005] = 
   sales['Bounce', 2001] + sales['Y Box', 2000] )
   --positional notation: permits insert of new cells 
   --for new product
ORDER BY country, prod, year
/

该示例数据没有超出 2001 年的值,因此所有涉及到 2002 年或之后的规则都要求插入新的单元格。对于此处定义的任何新产品名也是如此。在第三条规则中,2_Products 被定义为 2005 年的销售是 2001 年 Bounce 销售与 2000 年 Y Box 销售总和的产品。

对于 2002 年的 Bounce,第一个规则将插入新的单元格,因为这是位置表示法。对于 Y Box,第二个规则使用符号表示法,但是此处已经有了 2001 年的 Y Box 值,因此它将更新这些值。对于 2005 年的 2_Products,第三个规则是位置表示法,因此它可以插入新的单元格,您将在输出中看到这些新单元格。

在规则右侧使用多单元格引用

早先的示例只能在规则的左侧使用多单元格引用。如果要在规则右侧引用多个单元格,您可以在规则右侧使用多单元格引用,在这种情况下,需要对其应用聚合函数,以将它们转换为单一值。可以使用所有现有的聚合函数,包括 OLAP 聚合函数(逆分配函数、虚拟等级和分配函数等)、统计聚合函数以及用户定义的聚合函数。

1.您希望预测 2005 年 Bounce 在意大利的销售比其在 1999 至 2001 年间的最大销售多 100。为此,您需要在规则右侧使用 BETWEEN 子句来指定多个单元格,并通过 MAX() 函数将其聚合为单一值。从 SQL*Plus 会话中,执行以下脚本:

@c:\wkdir\multi_c.sql 

multi_c.sql 脚本包含以下内容: SELECT SUBSTR(country,1,20) country, 
SUBSTR(prod,1,15) prod, year, sales
FROM sales_view
WHERE country='Italy'
MODEL RETURN UPDATED ROWS
   PARTITION BY (country) 
   DIMENSION BY (prod, year)
   MEASURES (sale sales)
   RULES (
   sales['Bounce', 2005] = 
   100 + max(sales)['Bounce', year BETWEEN 1998 AND 2002] )
ORDER BY country, prod, year
/

请注意,聚合函数只出现在规则的右侧。聚合函数的参数可以是常量、约束变量、MODEL 子句的度量或者涉及这三种参数的表达式。

使用 CV() 函数和 ANY 通配符

CV() 函数是一个非常强大的工具,它可以高效地进行规则创建。CV() 用于规则的右侧,以复制左侧指定的当前维度值。对于左侧规范引用多个单元格来说,它非常有用。用关系数据库的概念来理解,该函数类似于连接操作。

CV() 允许使用非常灵活的表达式。例如,通过从 CV(year) 值进行减法运算,可以引用数据集中的其他行。如果您的单元格引用中有表达式“CV(year) -2”,您两年前就可以访问数据。CV() 函数通常作为单元格引用的一部分使用,但是也可以在单元格引用外部作为独立的表达式元素。

1.您希望更新 Bounce 在意大利多年的销售值,使用的规则是 Bounce 每年的销售是 Y Box 当年销售的 20% 与 Mouse Pad 当年销售的总和。从 SQL*Plus 会话中,执行以下脚本:

@c:\wkdir\cvf1.sql 

cvf1.sql 脚本包含以下内容: SELECT SUBSTR(country,1,20) country, 
SUBSTR(prod,1,15) prod, year, sales
FROM sales_view
WHERE country='Italy'
MODEL RETURN UPDATED ROWS
   PARTITION BY (country) 
   DIMENSION BY (prod, year)
   MEASURES (sale sales)
   RULES (
   sales['Bounce', year BETWEEN 1995 AND 2002] =
   sales['Mouse Pad', cv(year)] + 
   0.2 * sales['Y Box', cv(year)])
ORDER BY country, prod, year
/

请注意,在上述结果中,尽管接受了 1995–2002 年间的所有年份,您也只会看到 1999–2001 年的值。这是因为该表格只有这几年的数据。CV() 函数将提供左侧当前引用的单元格的 DIMENSION BY 关键字当前值。当上述规则的左侧引用单元格 Bounce 和 1999 时,右侧表达式将如下所示: sales['Mouse Pad', 1999] + 0.2 * sales['Y Box', 1999]

同样,当左侧引用单元格 Bounce 和 2000 时,右侧表达式将为: sales['Mouse Pad', 2000] + 0.2 * sales['Y Box', 2000]

CV() 函数将维度关键字作为其参数。还可以使用不带任何参数的 CV()(如 CV()),在这种情况下,暗示了位置引用。以上规则还可以写为: s['Bounce', year BETWEEN 1995 AND 2002] =

s['Mouse Pad', cv()] + 0.2 * s['Y Box', cv()]

CV() 函数只能在右侧单元格引用中使用。

2.您希望计算出产品 Y Box、Bounce 和 Mouse Pad 在意大利的销售年增长率。从 SQL*Plus 会话中,执行以下脚本:

@c:\wkdir\cvf2.sql 
cvf2.sql 脚本包含以下内容: SELECT SUBSTR(country,1,20) country, 
  SUBSTR(prod,1,15) prod, year, sales, growth
FROM sales_view
WHERE country='Italy'
MODEL RETURN UPDATED ROWS 
   PARTITION BY (country) 
   DIMENSION BY (prod, year)
   MEASURES (sale sales, 0 growth)
   RULES (
   growth[prod in ('Bounce','Y Box','Mouse Pad'), year between 1998 and 2001] =
   100* (sales[cv(prod), cv(year)] - 
   sales[cv(prod), cv(year) -1] ) / 
   sales[cv(prod), cv(year) -1] )
ORDER BY country, prod, year
/

请注意,结果中的空白单元格都是 NULL。如果没有前两年的产品值,那么规则将生成 NULL。由于没有一种产品有 1998 年的值,因此在任何情况下,1999 年的增长计算均为 NULL。

(T114)

技术文章快速查找

栏目导航
软件应用
·操作系统 ·杀毒防黑 ·应用软件
·聊天软件 ·网络软件  
Web开发
·ASP ·JavaScript ·CGI
·JSP ·VbScript ·Web服务器
·PHP ·XML  
开发语言
·VB ·VC ·ASP.NET
·Java ·C/C++ ·Delphi
数据库开发
·MySQL ·SQL/Access ·PowerBuilder
·Oracle ·DB2  
网站设计
·Flash ·Dreamweaver ·HTML/CSS
·Fireworks ·FrontPage  
平面设计
·Photoshop ·CorelDraw ·AutoCAD
·FreeHand ·Illustrator ·3DsMAX
媒体动画
·Director ·Authorware ·Maya
·视频处理    


相关软件 产品库推荐
·笔记本 ·台式机 ·服务器
·数码相机 ·手机 ·GPS
·DV摄像机 ·MP3 ·MP4
·CPU ·硬盘 ·内存
·主板 ·显卡 ·显示器
·打印机 ·投影机 ·路由器

还没人留言,抢个先,哈哈!
对"Oracle中使用SQL MODEL定义行间计算"的评论 - 快速回贴
内容:
  [完成后可按Ctrl+Enter发布]

百度中 Oracle中使用SQL MODEL定义行间计算 相关内容
Google搜索中 Oracle中使用SQL MODEL定义行间计算 相关内容
雅虎中 Oracle中使用SQL MODEL定义行间计算 相关内容
Sogou搜索中 Oracle中使用SQL MODEL定义行间计算 相关内容

相关软件 最新回复帖子:

·nesox让电子邮件营销原来如此轻松!
·Windows Vista 中卸载软件的不同方式
·没有mysql支持时的替代方案
·一个可以发送附件及HTML格式邮件的PHP类
·AutoCAD打造精致三维鸟笼实例详解
·Photoshop自定义水晶字特效样式
·AutoCAD三维基础实例教程
·PS为黑背景长发美女照片抠图换背
·用Photoshop自制个性摩托车贴花小经验
·轻松几步将美女照片处理为手工素描


  相关软件 Oracle中使用SQL MODEL定义行间计算相关文章
在MySQL中执行SQL语句时的几个注意点 向你谈谈SQLPlus中的复制和粘贴技巧
热点关注:IBM将与微软开始激烈对决 关于SQL Server数据库的若干注意事项
50种方法巧妙优化你的SQL Server数据库 优化SQL Server服务器内存配置的策略
将SQL语句转换为符合VB.NET格式字符串 用MS SQL Reporting Services生成报表
ACCESS转化成SQL2000需要注意的问题 限制SQL Server只能让指定的机器连接
SQL Server数据库的数据汇总完全解析 几种简单的损坏控制文件的恢复方法
告诉你使用SQL Server 2005的3个理由 教你SQL Server数据库安全规划全攻略
SQL Server日志文件总结及充满处理 SQL非正常删除日志文件(ldf)恢复方法
教你在Access数据库中如何使用SQL 教你如何来进行编写通用的数据访问
InstallShield10.5中项目选择简单介绍 九大措施教你安全配置SQL Server 2000