对异构数据库进行关联查询
例题描述和简单分析
Oracle数据库中,有 BRANCH 表,存储 DVD 分店信息,部分数据如下所示:
BID | STREET | CITY |
B001 | street1 | New York |
B002 | street2 | Houston |
B003 | street3 | LA |
B004 | street4 | Lincoln |
MySQL数据库中,有 DVD 表,存储 DVD 的标题及分类信息,部分数据如下所示:
DVDID | CATEGORY | TITLE |
D001 | science fiction | Transformers IV |
D002 | science fiction | Transformers II |
D003 | science fiction | Guardians of the Galaxy |
D004 | act | The Expendables III |
D005 | sport | Need for Speed |
D006 | feature | Grace of Monaco |
DVDID | Category | Title |
HSQL数据库中,有 DVDCOPY 表,存储 DVD 的多张拷贝,部分数据如下所示:
COPYID | DVDID | BID | STATUS | LASTDATERENTED | LASTDATERETURNED | MEMBERID |
C000 | D001 | B001 | 7/10/2014 | 7/13/2014 | M001 | |
C001 | D004 | B001 | 7/10/2014 | 7/13/2014 | M001 | |
C002 | D001 | B001 | 7/10/2014 | M001 | ||
C003 | D005 | B001 | 7/10/2014 | 7/13/2014 | M003 | |
C004 | D006 | B001 | 7/10/2014 | 7/13/2014 | M003 | |
C005 | D005 | B002 | 7/10/2014 | 7/13/2014 | M003 | |
C006 | D002 | B002 | 7/10/2014 | 7/13/2014 | M006 | |
C007 | D002 | B002 | 7/10/2014 | 7/13/2014 | M007 | |
C008 | D001 | B002 | 7/10/2014 | 7/13/2014 | M008 | |
C009 | D004 | B002 | 7/10/2014 | 7/13/2014 | M009 | |
C010 | D005 | B002 | 7/10/2014 | 7/13/2014 | M010 | |
C011 | D006 | B002 | Miss | 7/10/2014 | 7/13/2014 | M010 |
C000 | D001 | B003 | 7/10/2014 | 7/13/2014 | M001 | |
C001 | D004 | B003 | 7/10/2014 | 7/13/2014 | M001 | |
C002 | D001 | B003 | Miss | 7/10/2014 | M001 | |
C003 | D005 | B003 | 7/10/2014 | 7/13/2014 | M003 |
其中 DVDCOPY 表以 BID 字段和 BRANCH 表关联,以 DVDID 字段和 DVD 表关联。
需求 1:找出城市为 New York 的分店中所有的 DVD 拷贝的标题及分类信息,结果如下:
CITY | COPYID | CATEGORY | TITLE |
New York | C000 | science fiction | Transformers IV |
New York | C001 | act | The Expendables III |
New York | C002 | science fiction | Transformers IV |
New York | C003 | sport | Need for Speed |
New York | C004 | feature | Grace of Monaco |
需求 2:查询出缺货的 DVD 分店,即现存的 DVD 拷贝不到 4 类的分店,结果如下:
BID | STREET | CITY |
B002 | street2 | Houston |
B003 | street3 | LA |
B004 | street4 | Lincoln |
解法及简要说明
在集算器中编写脚本 p1.dfx,如下所示:
需求1:简单SQL
A | |
1 | =connect("demo").cursor@x("SELECT * FROM DVDCOPY") |
2 | =connect("mysql").cursor@x("SELECT * FROM DVD") |
3 | =connect("oracle").cursor@x("SELECT * FROM BRANCH") |
4 | $select b.CITY as CITY,dc.COPYID as COPYID,d.CATEGORY as CATEGORY,d.TITLE as TITLE from {A1} dc join {A2} d on dc.DVDID=d.DVDID join {A3} b on dc.BID=b.BID where b.CITY='New York' |
简要说明:
A1 连接数据源名为 demo 的数据库(HSQL),返回根据 sql 创建的数据库游标,关闭游标时自动关闭数据库连接
A2 连接数据源名为 mysql 的数据库(MySQL),返回根据 sql 创建的数据库游标,关闭游标时自动关闭数据库连接
A3 连接数据源名为 oracle 的数据库(Oracle),返回根据 sql 创建的数据库游标,关闭游标时自动关闭数据库连接
A3 用简单 SQL 关联三表
需求2:SPL
A | |
1 | =BRANCH=connect("oracle").query@x("SELECT * FROM BRANCH") |
2 | =DVD=connect("mysql").query@x("SELECT * FROM DVD") |
3 | =DVDCOPY=connect("demo").query@x("SELECT * FROM DVDCOPY") |
4 | =DVDCOPY.switch(DVDID,DVD:DVDID;BID,BRANCH:BID) |
5 | =DVDCOPY.select(STATUS!="Miss" && LASTDATERETURNED!=null) |
6 | =A5.group(BID) |
7 | =A6.new(~.BID:BonList,~.(DVDID).icount(CATEGORY):CatCount) |
8 | =A7.select(CatCount<4) |
9 | =A8.(BonList)|(BRANCH\A7.(BonList)) |
简要说明:
A1-A3:从数据库中检索数据,分别命名为变量 BRANCH、DVD、DVDCOPY。
A4:用 switch 函数,将 DVDCOPY 表中的 DVDID 字段切换成 DVD 表中对应的记录,将 BID 字段切换成 BRANCH 表中对应的记录。
A5:过滤数据:丢失的和未归还的 DVD 拷贝不在计算范围内
A6:A5 按 BID 分组,每组代表一个门店的所有 DVD 拷贝
A7:计算每个门店对应的 DVD 拷贝各有几类。函数 new 可以根据 A6 中的数据生成新的对象 A7,A7 有两个列:BonList 和 CatCount,BonList 直接来自 A6 中组内数据的 BID 列,CatCount 来自于组内数据的 DVDID 列。CatCount 的算法分为三部分:~.(DVDID) 找到每个门店所有的 DVD 拷贝对应的 DVD 记录;icount(CATEGORY) 用来计算 CATEGORY 去重后的个数。
A8:在 A7 中找出 CatCount 小于 4 的门店
A9:运算符“|”表示将两个数据集进行并集计算(可用 union 函数代替),运算符“\”表示差集计算(可用 diff 函数代替)。A8.(BonList)、BRANCH、A7.(BonList) 分别代表:DVDCOPY 表中缺货的门店、所有的门店、DVDCOPY 表中出现过的门店
JAVA 集成这段代码的方法可参考:《Java 如何调用 SPL 脚本》。
https://stackoverflow.com/questions/16991792/java-library-for-cross-database-retrieval