高效的可持续递归数据结构

时间:2011-02-21 08:29:11

标签: database data-structures recursion recursive-datastructures

递归数据结构的常用方法是在每个对象中都有一个父指针。我的问题是通常的实施无法在一次操作中回答以下问题;相反,我需要多次查询我的数据库。有没有一个解决方案可以在单个查询中提供结果?

  • 获取节点的所有子项列表

  • 查找所有父节点(==根节点的最短路径)

注意:我正处于计划阶段,所以我还不限于某个数据库。

2 个答案:

答案 0 :(得分:2)

如果“所有孩子”仅指直接孩子,只需输入一个孩子列表,以及指向每个节点上父母的指针。请注意,这将使节点移动到另一个父节点更加昂贵,因为所有(大)子节点也必须更新。

如果“所有孩子”真的意味着所有孩子,一个选项是构建每个父母的ID字符串,并将其添加为索引列。例如,如果您与孩子A B和孙子CC,则A/B/C列中的值为A。现在,要查找LIKE的所有子项,您只需在"A/%"上进行{{1}}查询即可。但是,当您需要更改具有子节点的节点的父节点时,这仍然很昂贵。

如果您需要能够快速更换父母,我认为您需要将父信息保存为链接列表。但是,您可以使用存储过程仅使用一次数据库往返来执行此查询操作。

答案 1 :(得分:2)

至少Oracle可以做hierarchical queries。考虑db用户角色的示例:

CREATE TABLE my_dba_role_privs(
   grantee        VARCHAR2(30),
   granted_role   VARCHAR2(30)
);   

-- assigning roles to roles
INSERT INTO my_dba_role_privs( grantee, granted_role ) VALUES('CLIENT', 'SELECT_ORDERS');
INSERT INTO my_dba_role_privs( grantee, granted_role ) VALUES('COMMERCIAL_DEP', 'CREATE_ORDERS');
INSERT INTO my_dba_role_privs( grantee, granted_role ) VALUES('COMMERCIAL_DEP', 'CLIENT');

-- assigning roles to users
INSERT INTO my_dba_role_privs( grantee, granted_role ) VALUES('CL_MATT', 'CLIENT');
INSERT INTO my_dba_role_privs( grantee, granted_role ) VALUES('CL_JOHN', 'CLIENT');
INSERT INTO my_dba_role_privs( grantee, granted_role ) VALUES('CM_MARY', 'COMMERCIAL_DEP');

现在选择用户'CM_MARY'的所有角色:

SELECT DISTINCT GRANTED_ROLE role_name
  FROM my_dba_role_privs
 START WITH GRANTEE = 'CM_MARY'
       CONNECT BY GRANTEE = PRIOR GRANTED_ROLE;   

结果:
COMMERCIAL_DEP
CREATE_ORDERS
CLIENT
SELECT_ORDERS

选择拥有“CLIENT”角色的所有角色和用户

SELECT GRANTEE role_name
  FROM my_dba_role_privs
 START WITH GRANTED_ROLE = 'CLIENT'
       CONNECT BY GRANTED_ROLE = PRIOR GRANTEE;   

结果:
CL_JOHN
CL_MATT
COMMERCIAL_DEP
CM_MARY

<强>更新
既然你提到过,树会非常静态,尝试Joe Celko's Trees(aprox 180行读取)可能会很有趣。 它根本不需要自联接!所以,我希望它的执行速度比CONNECT BY快。虽然我刚刚在30分钟前阅读过它,但不知道它在现实世界中的表现有多好

使用MySQL

Update2:“嵌套集模型”:Managing Hierarchical Data in MySQL这与上面的Joe Celko的树相同,但有更多示例和解释。