递归层次结构排名

时间:2016-06-15 15:48:17

标签: sql ms-access data-mining graph-theory

我不知道我是否写得正确。我想开始学习更高端的数据挖掘技术,我现在正在使用SQL服务器和Access 2016。

我有一个跟踪身份证的系统。每个ID都标记为安全层次结构的一个特定级别,该层次结构具有许多分支。

例如

Root
-Maintenance
 - Management
  - Supervisory
  - Manager
  - Executive
 - Vendors
  - Secure
  - Per Diem
 - Inside Trades

还有很多其他部门,比如维护,有些简单,有些则有更复杂的层次结构。

每个身份证都标记为一个级别,因此在维护示例中, - Per Diem:Vendors:Maintenance:Root。其他人可能只是标记给供应商,有些人只是标记维护本身(没有人有根,感谢上帝)。

所以我要说我已经选择了20张身份证,这些是我可以为工作任务的人员,但由于他们有不同的安全区域,我想找到一个共同点,他们可以作为一个20人组或其他人一起工作我可以做的其他分组。

所以预期的输出是

CommonMatch = - Per Diem
CardID = 1
CardID = 3

CommonMatch = Vendors
CardID = 1
CardID = 3
CardID = 20

所以在上面的例子中,虽然我可以让2个人参与-Per Diem工作,因为这是他们最低的共同安全相似性,还有持卡人#20谁拥有前任组(供应商)的权利, 1和3分享,所以我可以让他们中的三个在那个级别工作。

我不是在寻找任何人为我做这项工作(尽管总是欢迎这些例子),更多的是指出我应该学习的正确方向,我正在努力做的事情,等等。我知道CTE是一种方法,但这似乎只是一个需要完成的更大过程中的工具。

提前谢谢大家

1 个答案:

答案 0 :(得分:0)

嗯,它不是一个图论或数据挖掘问题,而是一个数据结构问题,而且几乎已经解决了问题。

目标是能够在给定安全许可级别的情况下将卡ID集划分为不相交的子集。

因此,这里的主要思想是布局层次结构树,然后将每个卡ID分配给其安全级别许可隐含的路径。为此目的,层次树的每个节点现在变成卡ID的容器(例如,层次树的每个节点保持a)其自己的名称(作为唯一标识)b)指向其他节点的指针c)分配的卡ID列表它的名字"。)

然后,检索具有间隙 UP TO 特定安全级别的卡片组只是从特定级别向下遍历树<#>到树#39 ; s leafs,一直从遇到的节点容器中收集卡ID。

假设我们有访问树:

A
+-B
+-C
D
+-E

卡片ID分配:

B:[1,2,3]
C:[4,8]
E:[10,12]

目前,B,C,E仅作为标签有意义,没有与之相关的结构信息。因此,我们需要首先构建&#34;那个树。以下示例使用Networkx,但可以通过多种方式实现相同的目标:

import networkx
G = networkx.DiGraph() #Establish a directed graph
G.add_edge("A","B")
G.add_edge("A","C")
G.add_edge("A","D")
G.add_edge("D","E")

现在,将卡ID分配给节点容器(在Networkx中,节点可以是任何有效的Python对象,因此我将使用非常简单的列表)

G.node["B"]=[1,2,3]
G.node["C"]=[4,8]
G.node["E"]=[10,12]

所以,现在,让每个人都在&#34; A&#34; (树的根),您可以通过Depth First Search (DFS)Breadth First Search (BFS)从该级别向下遍历树,并从容器中收集卡ID。我将在这里使用DFS,纯粹是因为Networkx直接根据访问顺序a function that returns the visited nodes

#dfs_preorder_nodes returns a generator, this is an efficient way of iterating very large collections in Python but I am casting it to a "list" here, so that we get the actual list of nodes back.
vis_nodes = list(networkx.dfs_preorder_nodes(G,"A")); #Start from node "A" and DFS downwards
cardIDs = []
#I could do the following with a one-line reduce but it might be clearer this way
for aNodeID in vis_nodes:
    if G.node[aNodeID]:
        cardIDs.extend(G.node[aNodeID])

在上述迭代结束时,cardID将包含来自分支&#34; A&#34;的所有卡ID。在一个方便的列表中向下。

当然,这个例子非常简单,但是由于我们讨论的是树,树可以像你想的那样大,你仍然以同样的方式遍历它,只需要一个入口点(顶层)分支)。

最后,作为一个注释,您使用Access作为后端的事实不一定是障碍,而是关系数据库do not handle graph type data with great ease。你可能很容易就像一棵简单的树(就像你在这里所拥有的那样)而逃脱,但是支持这个的麻烦可能有理由在数据库之外进行这个过程(例如,使用数据库只是为了检索数据并执行在不同的环境中进行图形类型数据处理。在SQL上执行DFS是我上面提到的那种麻烦。)

希望这有帮助。