相邻列表模型树,防止循环

时间:2016-04-19 19:57:38

标签: sql tree circular-reference adjacency-list-model

示例表:

CREATE TABLE adj_list_model (
    id INT NOT NULL AUTO INCREMENT,
    parent_id INT,
    my_string varchar(255),//some random information
    PRIMARY KEY (id)
)

我正在创建的树将有多个" root"同一个表中的用户(当parent_id = NULL时)。这些" root"用户可能在某个时候 从某些" leaf"中获取parent_id。 user(在其下没有人的用户)。我的疑问是如何确保我不创造 a"循环"类似于以下一个:

示例树设计:

  • 一个
    • B'/ LI>
    • C
      • d
        • ë
        • ˚F

如果用户" a"获得用户" g"作为他的父母,那么创建的循环将是:

a -> c -> d -> f -> g -> a -> c... and so on forever

问题:检查用户是否" g"在用户" a"当用户" a"想要去用户" g"在树上? (以便在那些特定情况下可以防止这种行为)

要考虑的要点: 将两棵树合并成一棵树会经常发生。如果树中的级别数量假设为80,那么进行检查以防止循环可能需要的时间量可能相当大,这就是我寻找有效方法的原因。

编辑: 我当前的选择(虽然我持怀疑态度)是:

  1. 创建一个额外的列,显示当前" root"表中每个用户的用户。在这种情况下,每次" root"用户获得了父母,他下面的每个人都必须使用新的" root"用户,让我担心的是这可能会给服务器带来多大的压力,特别是如果有很多用户并且频率很高的" root"用户获得父母。

  2. 检查" root"在给他父母之前的用户路径。如果在上面的情况下用户" g"通过循环遍历g 1乘1的每个用户检查他的路径(看到他们的父亲是什么,一遍又一遍,直到到达根),并发现root是用户" a"然后是,虽然我不确定服务器上的这种情况会有多紧张,但可以防止这种情况发生。如果有人有想法,请告诉我!

1 个答案:

答案 0 :(得分:1)

对于带有其他 root_id 列的选项,在MySql语法中:

CREATE PROCEDURE change_root() 
BEGIN

  # this is the leaf node id, which will be the new parent of a root user
  SET @new_parent = x;
  # this is the old root user id, which will be the new child of the former leaf node
  SET @old_root = y;
  # get the leaf's root
  SET @new_root = SELECT root_id FROM adj_list_model WHERE id=x;

  # updating the dataset is possible as long as the leaf is not a child of the root user
  IF @new_root <> y THEN

    # link the former leaf to its new child
    UPDATE adj_list_model SET parent_id=x WHERE id=y;

    # @old_root is no longer a root, so update all occurences to the new root
    UPDATE adj_list_model SET root_id=@new_root WHERE root_id=@old_root;

  END IF;

END;

这实际上并不比递归解决方案复杂且快得多。但最终它取决于您的工作量和需求。