【问题标题】:Recursive Hierarchy Ranking递归层次排序
【发布时间】:2016-06-15 15:48:17
【问题描述】:

我不知道我是否写对了。我想开始学习更高端的数据挖掘技术,我目前正在使用 SQL Server 和 Access 2016。

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

例如

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

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

每个 ID 卡都被标记到一个级别,因此在维护示例中 - 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 是一条路要走,但这似乎只是一个需要完成的更大流程中的工具。

提前谢谢大家

【问题讨论】:

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


    【解决方案1】:

    嗯,这与其说是图论或数据挖掘问题,不如说是一个数据结构问题,而且几乎已经自行解决了。

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

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

    然后,检索具有 UP TO 特定安全级别的权限的卡片组只是一个简单的情况,即从该特定级别向下遍历树 直到树的叶子,一直在收集节点容器中遇到的卡 ID。

    假设我们有访问树:

    A
    +-B
    +-C
    D
    +-E
    

    和卡ID分配:

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

    目前,B、C、E 仅作为标签有意义,没有与它们相关的结构信息。因此,我们需要首先“构建”树。以下示例使用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]
    

    所以,现在,为了让每个人都在“A”(树的根)下工作,您可以通过 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])
    

    在上述迭代结束时,cardIDs 将在一个方便的列表中包含从分支“A”向下的所有卡 ID。

    当然,这个例子非常简单,但是由于我们讨论的是树,所以树可以任意大,并且您仍然以相同的方式遍历它,只需要一个入口点(顶层分支)。

    最后,请注意,您使用 Access 作为后端这一事实不一定是障碍,而是关系数据库do not handle graph type data with great ease。您可能会因为简单的树之类的东西(例如您在此处所拥有的)而轻松逃脱,但是支持这一点的麻烦可能证明在数据库之外执行此过程是合理的(例如,仅使用数据库来检索数据并执行图类型数据在不同环境中的处理。在 SQL 上做 DFS 是我上面提到的那种麻烦。)

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2021-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-22
      • 2017-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多