用R语言igraph库实现表自动关联

来源:互联网 发布:虹云网络 编辑:程序博客网 时间:2024/05/18 15:53
数据库和图算法结合的一个问题:
自动表关联的问题:一个数据库(图),有N个表(图的顶点),表之间通过外键建立关联(图的边)。
已知用户的一个查询必然涉及其中M个表,但程序不知道这几个表通过什么外键建立起join关系。
要求:让程序自动找出用哪几个表做join可查出结果,并列出表的join顺序(不用最优)。
抽象后的问题:N个顶点的图中找出经过M个顶点的最小连通图


算法:
1. 图是顶点数为N的无向图。
2. 得到必经顶点集M中长度为2的全组合CM。
3. 找出全组合CM中每两个顶点的最短距离minp。
4. 选择路径最短的两个顶点minminp,并且这两个顶点作为访问过的顶点集visitedTbls。M中visitedTbls之外的集合为unvisitedTbls
5. 以visitedTbls中所有顶点为源点,以unvisitedTbls中所有顶点为目标顶点构造两点最短路径,并选择这些最短路径中的最短路径,然后去掉这条路径中的源点,把这条路径中其它顶点加入visitedTbls
6. 重复5直到unvisitedTbls为空
7. 如果visitedTbls集合包含M,则正常。否则M中表存在不连通的情况,提醒用户。


用igraph R实现算法:
--------------
library(igraph)
#用数据库中所有表构造图
g = make_graph(c("student", "class", "student", "scourse", "student", "exam", "teacher", "tcourse", "class", "tcourse", "tcourse", "scourse", "tcourse", "exam"), directed = FALSE)
#用户需要的表
tbls <- c("teacher", "scourse", "exam")
#所有路径
all_simple_paths(g, "student", "tcourse")
candidates <- combn(tbls, 2)

candPath <- c()
shortest <- 100
shortp=1
visitedTbls <- c()
unvisitedTbls <- c()

for (i in 0:(dim(candidates)[2] - 1)) {
  #有多条最短路径的选择第一个
  ps <- all_shortest_paths(g, candidates[i*2+1], candidates[i*2+2])$res
  if(length(ps) > 1)
candPath <- c(candPath, list(ps[[3]]))
  else 
    candPath <- c(candPath, list(ps[[1]]))
}


for(i in 1:length(candPath)) {
if(length(candPath[[i]]) < shortest) {
shortest = length(candPath[[1]])
shortp = i
}
}

#开始循环
visitedTbls <- c(visitedTbls, list(candPath[[shortp]]$name), recursive=TRUE)
unvisitedTbls <- setdiff(tbls, intersect(tbls, visitedTbls))

run <- 1
while(run) {
candPath <- c()
shortest <- 100
shortp <- 1

for (i in visitedTbls) {
 for (j in unvisitedTbls) {
   if(i != j) {
res = all_shortest_paths(g, i, j)$res
   #用户需要的表存在不连通的情况,停止发警告。
if(length(res) == 0)
run <- 0
else
candPath <- c(candPath, list(res[[1]]))
}
 }
}

for(i in 1:length(candPath)) {
if(length(candPath[[i]]) < shortest) {
shortest = length(candPath[[1]])
shortp = i
}
}
visitedTbls <- c(visitedTbls, list(setdiff(candPath[[shortp]]$name, candPath[[shortp]]$name[1])), recursive=TRUE)
unvisitedTbls <- setdiff(tbls, visitedTbls)
if(length(unvisitedTbls) == 0)
break
}
if(!all(tbls%in%visitedTbls))

print("用户需要的表存在不连通")

#输出结果

visitedTbls


算法效果:

图如下:


用户要找"teacher", "scourse", "exam"三个表的关联关系。

输出join路径:"teacher" "tcourse" "scourse" "exam"   即((teacher join tcourse) join scourse) join exam 

原创粉丝点击