Oracle Technology Network (OTN) > Downloads, Discussions, and Documentation for Developers and DBAs

商务智能

在企业报表中使用位置信息
作者:Justin Lokitz 和 Madeline Alameda

了解如何创建动态地图,此动态地图可以使属性和基于位置的信息之间的关系更加清晰

下载本文的 JDeveloper 项目文件

位置信息无处不在;可以在各种公司、所有行业,以及几乎世界上每一个机构和部门中找到位置信息。然而,大多数机构仅用以下两种方式之一处理位置信息:

  • 位置为地址 — 通常与一个实体的名称或 ID 相关,并用来支持一种业务功能(如计费或邮寄),或在一个报表环境中将某些记录与其它类似的记录区分开。例子包括销售和服务机构的应用程序、以及人力资源和营销应用程序。
  • 地图上某一点的位置 — 仅用于描绘单个点或位置,以与其它的点、位置和/或主题区分开,并只能由地理信息系统 (GIS) 用户访问。

虽然位置信息对于使上述两种系统的运转非常关键,但它最终很少用来集成这些系统中的数据并为机构提供可操作的商务智能。

这并不广为人知,但利用目前的技术,不仅将位置作为一个地址或地图上的一个点来使用,而且确实可以将其作为一种根据市场份额、人口集中度或复杂的基于位置的交互来揭露趋势的方法来使用。在本文中,我们将说明一种用来帮助各种公司实现这一目标的技巧,该技巧使用的企业报表工具与关系数据常用的工具相同。

从位置信息中获取智能

在数据库中存储 GIS 信息至少有三种方法:以专有格式(一般为 BLOB 或 Long Raw),以纯 X、Y 坐标的形式,或使用一种与 OpenGIS 兼容的对象类型(如 Oracle Spatial SDO_GEOMETRY 类型)。

在前两种情况下,为了从数据库中取出位置信息,并将其与属性信息关联,开发人员必须使用第三方的中间件或书写程序。然而,利用 Oracle 的 SDO_GEOMETRY 对象格式来存储和管理位置数据,开发人员可以将标准 SQL 和 GIS 功能一起使用,以从位置和属性数据中提取智能。

看看下面的 Oracle 示例:执行基于位置的分析。给定两个表 Customers 和 Warehouses,我们使用几种数据类型(如常见的 NUMBER、VARCHAR2、XMLTYPE 以及用户定义的类型)来存储数据。然而,您还将注意到有第 5 种类型,MDSYS.SDO_GEOMETRY,它是一种用来存储客户或仓库在地球表面上的点位置的 Spatial/Locator 类型。

Customers 表有以下字段:

                  数据类型
customer_id           NUMBER(6)
cust_first_name       VARCHAR2(20)
cust_last_name        VARCHAR2(20)
cust_address          cust_address_typ
phone_numbers         phone_list_typ
nls_language          VARCHAR2(3)
nls_territory         VARCHAR2(30)
credit_limit          NUMBER(9,2)
cust_email            VARCHAR2(30)
account_mgr_id        NUMBER(6)
cust_geo_location     MDSYS.SDO_GEOMETRY 

Warhouses 表有以下字段:

                 数据类型
warehouse_id          NUMBER(3)
warehouse_spec        SYS.XMLTYPE
warehouse_name        VARCHAR2(35)
location_id           NUMBER(4)
wh_geo_location       MDSYS.SDO_GEOMETRY

详细查看 Customers 表中的 cust_geo_location 列,我们将看到它的描述如下:

CUST_GEO_LOCATION(SDO_GTYPE, SDO_SRID, SDO_POINT(X, Y, Z), SDO_ELEM_INFO, SDO_ORDINATES)

从这个描述中我们可以确定存储的数据的几个特性:

  • SDO_GTYPE 描述几何结构类型(点、线、或多边形)
  • SDO_SRID 用来描述坐标系统
  • SDO_POINT 描述维度和经度
  • SDO_ELEM_INFO 描述如何使用存储在 SDO_ORDINATES 部分中的数字
  • SDO_ORDINATES 描述组成一个空间目标的边界的坐标值。

查看单列的数据 (SDO_GEOMETRY(2001, 8307, SDO_POINT_TYPE(6.1667, 46.2, NULL), NULL, NULL)),我们看到对于点数据,只用到了前三个 SDO_GEOMETRY 属性。以这种方式存储位置数据实现了灵活性,并且允许通过标准访问方法(如 SQL、JDBC 和 ODBC)进行访问。

我们现在可以使用 SQL*Plus 和 Spatial/Locator 操作符查询 Customers 表中的位置和属性信息。看看下面的示例:

SELECT a.cust_last_name
FROM customers a
WHERE
SDO_WITHIN_DISTANCE(a.cust_geo_location, mdsys.sdo_geometry (2001, 8307,
mdsys.sdo_point_type (6.1667, 46.2, null), 
null, null),
'distance=20000 unit=meter') = 'TRUE';

如果我们研究这条查询(图 1),我们在选择地球上一点 (6.1667, 46.2) 周围的 20,000 米(20 千米)以内的每个客户的姓:

图 1
图 1:查找 20,000 米内的客户的查询

以上这个简单的查询很有趣,但我们实际上想从位置和属性信息中提取的是一个结果集,这个结果集能够告诉我们我们的客户可能如何与我们的仓库交互。因此,以下 SQL 查询查找离 warehouse_id=2 的仓库最近的十个客户的名称,以及客户离给定的仓库具体有多远(以米为单位):

select /*+ordered*/ 
c.customer_id, 
c.cust_first_name, 
c.cust_last_name,
sdo_nn_distance (1) distance
from warehouses w, 
customers c
where w.warehouse_id = 2
and sdo_nn (c.cust_geo_location, w.wh_geo_location, 'sdo_num_res=5', 1) = 'TRUE'
order by distance;

同样,看看这条查询的每一部分(图 2):

图 2
图 2:查找离仓库最近的 10 个客户的查询

以上查询显示了如何从数据库中检索位置和属性数据,甚至查找与数据的关系。接下来,我们将看看我们如何能够在一个企业报表系统 (ERS) 中使用这些查询,从而使最终用户能够自己查看这些信息。

在 ERS 中使用位置信息

现在我们可以使用标准 SQL 来查找存储在不同表中的位置和属性数据之间的关系,我们将看看在 ERS 中部署这种功能的方法。大多数这种系统支持用标准 SQL 来返回结果集。因此,我们现在将能够通过任意的这种工具来使用前一部分中的 SQL。在这种情况下,我们将把包含 GIS 结果集的 SQL 集成到 Oracle Application Server Discoverer 中。

在 Discoverer 中的最终用户的视图中,关系和元数据中的其它特性被 Discoverer Administrator 提取了出来。在与存储我们的位置信息的 Oracle 数据库例程连接之后,我们必须首先构建业务数据区(图 3 — 6)。这个操作假定已经创建了 Discoverer 终端用户层 (EUL) — 这个过程超出了本文的范围。(由于详细信息,请参见 Discoverer 管理员指南)。

图 3
图 3:创建一个业务数据区。

图 4
图 4:选择要访问的表的用户模式(例如,用户 OE)。

图 5
图 5:在业务数据区中选择您想要的表。

图 6
图 6:为业务数据区给定一个名称(例如,"10 Closest Customers"),然后单击 "Finish"。

在创建了一个业务数据区之后,我们必须定义用户调用 OE 模式表(Customers 和 Warehouses)中的位置数据的方式。为此,我们创建了一个将包含上一部分中的 SQL 语句的定制文件夹,这些 SQL 语句包含在以下查询中:

select /*+ordered*/ c.customer_id, 
c.cust_first_name, 
c.cust_last_name,
c.account_mgr_id,
w.warehouse_id, 
sdo_nn_distance (1) distance
from warehouses w, 
customers c
where sdo_nn (c.cust_geo_location, w.wh_geo_location, 'sdo_num_res=10', 1) = 'TRUE'
order by distance;

注意我们已经将 w.warehouse_idc.account_mgr_id 添加到了查询的正文中。这样我们就能够从 Discoverer 中根据任意的仓库或客户经理来动态运行查询。图 7 显示了定制文件夹中的这一查询,我们将之称为 "Distance"。

图 7
图 7:插入一个定制文件夹,以保存和验证我们的 GIS SQL 语句

我们现在有了一个 Discoverer 业务区域和一个包含了属性和位置数据的名称为 Distance 的文件夹。此时,我们可以部署这个业务数据区,以便我们的最终用户能够在报表中使用数据,或者我们可以更进一步,为他们提供一个辅助的信息集:一个动态、智能的地图。

使用动态地图

“查看”位置信息的最强大的方式可能就是通过地图。在上述例子中,我们使用标准查询和报表技术提取了位置和属性数据;然而,在很多情况下,地理特性只有在地图上进行查看时才能察觉到。因为我们有一个大数据集和许多需要查看数据的最终用户,所以我们将提供一个使最终用户能够向下查看任意给定报表的详情的企业报表前端,该企业报表前端将反过来与一个动态的、基于 web 的地图连接 — 从而以表格和地图的形式为最终用户提供所有的详情。

许多 GIS 和制图工具支持部署这种地图。在这个演示中,我们将使用 Oracle Application Server MapViewer — 使用由 Oracle Spatial/Locator 管理的位置数据来绘制地图的一种 J2EE 服务。因为 MapViewer 通过 XML 与客户端通信,所以它的工作原则是任何能够以 XML 格式发出请求和接收回复的东西本质上都可以成为 MapViewer 客户端。此外,因为 MapViewer 是一种 J2EE 服务,所以它自带了一个 Java API 和一个 JSP 标记库。

与其它的地图绘制工具相同,MapViewer 使用样式(颜色、标志、线、区域、文本、符号和高级样式)和主题(有时称为层)的概念来创建动态地图。这些属性的定义以及实际地图的定义都以 XML 的格式和位置信息一起存储在数据库中。

要创建属性和/或地图定义,我们可以对数据库执行标准的 SQL 插入/更新,如:

SQL> insert into USER_SDO_STYLES values(
'V.PIECHART1', 'ADVANCED', null, 
'<?xml version="1.0" ?>
<AdvancedStyle>
<PieChartStyle pieradius="10">
<PieSlice name="A"    color="#ffff00" />
<PieSlice name="B"    color="#000000" />
<PieSlice name="H"    color="#ff00ff" />
<PieSlice name="I"    color="#0000ff" />
<PieSlice name="W"    color="#ffffff" />
</PieChartStyle>
</AdvancedStyle>',  null, null);

或者,我们可以使用提供的地图定义工具(图 8),它将为我们完成大部分工作:

图 8
图 8:地图定义工具

Oracle 应用服务器中包含的标准 MapViewer 下载或部署,包括一系列的样式、主题、基本地图和示例代码。不过,在我们的示例中,我们将需要复制一个基本地图并添加两个主题。因为我们能够通过 SQL 和工具来访问数据库中的地图定义,所以复制地图定义的最容易的方法是执行类似以下的 SQL 语句。(在这么做之前,请查看与 MapViewer 相关的视图 user_sdo_styles、user_sdo_themes 和 user_sdo_maps,以更好地理解它们的工作方式。)

SQL> insert into user_sdo_maps
2  values('WAREHOUSES_AND_CUSTOMERS', 'customers and warehouses',
3  (select definition from user_sdo_maps where name='DENSITY_MAP'));

1 row created.

SQL> commit;

Commit complete.

我们现在有了一个新的基本地图(名称为 WAREHOUSES_AND_CUSTOMERS),我们将使用地图定义工具在其中添加一些主题。首先,转至包含 mapdef.jar 的目录,并执行以下命令来与存储我们的地图定义的 Oracle 数据库实例连接:

java -classpath mapdef.jar;d:\oracle\ora92\jdbc\lib\classes12.jar - Dhost="localhost" -
Dsid="orcl" -Dport="1521" oracle.eLocation.console.GeneralManager

接着,创建两个主题,CUSTOMERS 和 WAREHOUSES (图 9 和 10):

图 9
图 9:创建 CUSTOMERS 主题

图 10
图 10:创建 WAREHOUSES 主题

在创建了客户和仓库主题之后,将它们添加到我们新的 WAREHOUSES_AND_CUSTOMERS 基本地图中(图 11):

图 11
图 11:创建 WAREHOUSES_AND_CUSTOMERS

注意 Min Scale 和 Max Scale 元素。这些元素用来根据要求的缩放等级定义哪些主题出现在指定的地图上。

在(通过 Update 按钮)更新地图定义之后,我们可以开始使用它们来根据客户机请求构建动态地图。测试我们的地图是否正常工作的一种容易的方法是将这个新的地图定义名称 (WAREHOUSES_AND_CUSTOMERS) 插入到我们的演示 MapViewer 应用程序中。为此,转至我们的 MapViewer 简单地图客户端(MapViewer URL 上的 mapclient.jsp),并输入必需的值(图 12):

图 12
图 12:演示地图客户机

注意 mapclient.jsp 示例应用程序还显示向 MapViewer 服务器发出的请求 — 这是和由任意客户机或开发语言发出的请求相同的 XML 请求。如果所有的定义和连接值都正确,那么将根据请求构建一个地图(或到地图影像的一个 URL)。

在我们的例子中,我们将使用和 MapViewer 一起提供的 demo/tagmap.jsp 文件。在运行提供的 tagmap.jsp 之后,我们可以与它的源代码连接,并开始修改它,以使它适合我们的 BI 查询模式。如果使用合适的工具,修改和测试 JSP 可能是一项容易的任务。在这个演示中,我们将使用 Oracle JDeveloper 10g 和相关的 Oracle 应用服务器 10g MapViewer JSP 标记库。(在此下载 JDeveloper 项目文件。)

要根据请求动态地为 cust_geo_location 列中的数据创建地图,请修改 tagmap.jsp(我们将之重命名为 oemap.jsp),以包含打开数据库连接、执行查询和检索结果集的方法。通常您将使用 JDBC 或类似的技术来执行数据库操作。不过,因为 Oracle Application Server MapViewer 已经使用了 JDBC 来从数据库中获取地图定义,所以我们可以使用提供的 MapViewer Java API 来为我们创建所有的连接:我们需要操心的只是编写查询。

要访问我们的 Customers 表,请执行一条查询,并提供要在我们的地图中使用的维度和经度变量,并将以下代码添加到 oemap.jsp 中。注意 custid JSP 参数:这个参数在 SQL 查询中使用,并将过滤结果集,从而根据单个客户 ID 创建动态地图:

String mvURL = "http://www.foo.com:8888/mapviewer/omserver";
MapViewer mv = new MapViewer(mvURL);
String custid = request.getParameter("custid");
String latitude = "";
String longitude = "";
String sqlQuery = "SELECT c.cust_first_name, c.cust_last_name, t.X, t.Y FROM   customers c, 
TABLE(SDO_UTIL.GETVERTICES(c.cust_geo_location)) t where c.customer_id ="+custid;
String[][] qryRes = mv.doQuery("mvdemo",sqlQuery);

在执行查询操作并获得一个结果集之后,显示结果集并相应地设置维度和经度参数(图 13)。

图 13
图 13:增加变量、查询操作并显示结果。

在执行查询并设置维度和经度变量之后,使用以下代码来设置 MapViewer 标记和一个特殊的 JDBC 主题(用来在地图的中心显示一个红星;参见图 14):


<mv:init url="<%=mvURL%>"datasource="mvdemo" id="mvHandle"/>
    
<mv:setParam title="Customer/Warehouse Map" bgcolor="#ffffff" width="500" height="375" antialiasing="true" />

<mv:importBaseMap name="WAREHOUSES_AND_CUSTOMERS"/>
    
<mv:setParam centerX="<%= latitude %>" centerY="<%= longitude %>" size="3"/>

动态地添加主题,以查找并用一个红星来标识地图上的单个点:

<%
mvHandle.addJDBCTheme("mvdemo", "centerPoint","SELECT mdsys.sdo_geometry(2001, 8307, 
mdsys.sdo_point_type("+ latitude +","+ longitude +", null), null, null)  geom FROM dual","geom", 
null, "M.STAR", null, null, true);  
%>

图 14
图 14:MapViewer 标记和 JDBC 主题

在对地图代码做了一些小修改之后,从 JDeveloper 中测试地图的部署,设置 custid JSP 参数,并获得以下结果(图 15):

图 15
图 15:新创建的动态定制地图

当地图的外观和行为都与预期一致时,将地图部署至一个 Oracle 应用服务器实例。

我们终于准备好了将我们的 Discoverer 报表与我们的动态定制地图连接。为此,转回至 Discoverer 管理工具,并在 Distance 文件夹上创建一个 calculation 列。该列将保存与动态地图连接的 URL。

用 Distance 文件夹上的光标,单击 "New Calculation" 图标(图 16)。这个新的 Calculation 列被命名为 MAP URL。

图 16
图 16:New Calculation 图标

在该向导的 Calculation 部分中,输入地图的 URL,将 Discoverer Customer Id 字段连接在该 URL 的末尾,以使得对于每一条返回到 Discoverer 报表中的记录,都将存在一个不同的 custid JSP 参数(图 17)

图 17
图 17:输入 URL 并将 Customer Id 与 calculation 字段连接。(URL 显示为:http://www.foo.com:8888/OEMaps/oemap.jsp?custid='||Customer Id)

现在一个动态 URL 将与每一条要返回的记录关联在一起,从而确保当用户单击 URL 时,一个新的显示动态地图的地图窗口将打开。为此,双击新的 MAP URL 计算,这将把我们带到该列的属性窗口。在 Content Type 属性下,选择 "File" (图 18)。

图 18
图 18:将 Content Type 修改为 "File"

我们现在准备好了设置我们的 Discoverer 报表并测试我们的动态地图。Discoverer Desktop 和 Discoverer Plus 是使最终用户能够登录数据库并根据 Discover Administrator 设置的信息来创建动态报表的查询工具。因此,请作为最终用户登录到 Discoverer Desktop 中,并开始创建一个新的报表(并将其作为一个页面从表显示)的过程(图 19)。

图 19
图 19:创建新的 Discoverer 报表

因为我们与数据库连接在一起并被授予了合适的权限,所以我们能够确定哪些字段对我们的报表很重要。在这种情况下,选择 Distance 文件夹中的所有字段(图 20)。

图 20
图 20:报表字段

我们的报表的布局使我们能够根据 Warehouse ID 和 Account Manager ID 动态地向下查看信息(图 21)。

图 21
图 21:报表布局

要提供一个与默认不同的排序方式,请为 Distance 列创建一个组排序,以根据客户离某个特定的仓库有多远来提供信息 — 从最近到最远(以米为单位)(图 22)

图 22
图 22:创建排序。

在完成了利用 Discoverer 向导来创建报表的过程之后,我们可以从 Discoverer Desktop、Discoverer Plus 或 Discoverer Viewer 中运行报表。注意为报表的每一行创建的动态 URL (图 23)。

图 23
图 23:从 Discoverer Plus 中运行报表

最后,最终用户和开发人员都能够以一种信息化和便捷的方式查看位置信息(图 24)。

图 24
图 24:眼见为实。

位置信息的普遍性

无论您在处理仓库的客户订单还是在查看地图上的人口集中度,位置驱动着所有的事务,并始终与非位置的属性信息关联。利用动态地图,查找属性和基于位置的信息之间的关系要更容易得多。

有关 Oracle Application Server MapViewer 的详细信息,请参见 otn.oracle.com/products/mapviewer/index.html

有关使用 SDO_GEOMETRY 数据的详细信息,请参见 Oracle Spatial 用户指南和参考download-west.oracle.com/docs/cd/B13789_01/appdev.101/b10826/toc.htm


Justin Lokitz 是 Oracle Corporation 的一位专门研究 GIS 和 J2EE 开发的高级销售顾问。Madeline Alameda 是 Oracle Corporation 的一位专门研究商务智能和数据仓库的销售顾问人员。

请为本文评定等级:

优秀 良好 一般 低于一般水平 较差


把您的意见发送给我们

E-mail this page
Printer View Printer View