【问题标题】:Repair Broken Nested Set修复损坏的嵌套集
【发布时间】:2009-10-05 18:06:26
【问题描述】:

我必须通过脚本或 sql 修复损坏的嵌套集合链。该表包含一个左值列和一个右值列,但没有父 id 列。 我能够计算嵌套集中每个节点的级别。左右值存在差距。计算级别的结构是有效的。 有人知道通过 SQL 缩小差距的解决方案吗? (MySQL)

没有任何建议适合我的问题,但感谢您的参与。

我为我制定了一个解决方案: 1. 第一步计算父ID并转换为邻接表 2.使用Joe Celko的方法将邻接表转换为嵌套集 3.更新旧的左右值

【问题讨论】:

  • 所以你想像在邻接列表中一样存储父 ID(另外还有左/右)?

标签: php mysql


【解决方案1】:

我会从你拥有的左右值生成一个 parent_id 列,然后重新生成左右值。

如果您不想修改当前表,您甚至可以在临时表中执行此操作。

【讨论】:

  • 我必须同意 - 如果没有 parent_id,你就完蛋了。或者至少这是我在处理同样的问题后发现的。
  • 我通过使用以下 SQL 解决了计算 parent_id(没有父列)的问题:SELECT A.id, IF(B.id IS NULL, 1, B.id) AS parent FROM page AS A LEFT OUTER JOIN page AS B ON B.tree_lft = (SELECT MAX(C.tree_lft) FROM page AS C WHERE A.tree_lft > C.tree_lft AND A.tree_lft
【解决方案2】:

节点 (c) 的每个祖先都有一个较小的 left 和较大的 right 值。而直接父级 (p) 是该集合(祖先)中具有最大 left 值的那个。

例如

CREATE TABLE nested (
  id int AUTO_INCREMENT,
  name varchar(16),
  parentid int DEFAULT 0,
  lft int(11),
  rgt int(11),
  PRIMARY KEY (id)
)

INSERT INTO
    nested (name, parentid, lft, rgt)
VALUES
    ('1'      ,0,1,20),
    ('1.1'    ,0,2,9),
    ('1.1.1'  ,0,3,4),
    ('1.1.2'  ,0,5,6),
    ('1.1.3'  ,0,7,8),
    ('1.2'    ,0,10,19),
    ('1.2.1'  ,0,11,14),
    ('1.2.1.1',0,12,13),
    ('1.2.2'  ,0,15,16),
    ('1.2.3'  ,0,17,18)

SELECT
  p.id as pid, p.name as pname,
  c.id as cid, c.name as cname  
FROM
  nested as c
LEFT JOIN
  nested as p
ON
  p.lft=(
    SELECT
      MAX(lft)
    FROM
      nested AS l
    WHERE
      c.lft > l.lft
      AND c.lft < l.rgt
  )

返回

pid    pname    cid    cname
NULL   NULL     1      1
1      1        2      1.1
2      1.1      3      1.1.1
2      1.1      4      1.1.2
2      1.1      5      1.1.3
1      1        6      1.2
6      1.2      7      1.2.1
7      1.2.1    8      1.2.1.1
6      1.2      9      1.2.2
6      1.2      10     1.2.3

【讨论】:

    【解决方案3】:

    嵌套集中有 4 或 5 种不同的损坏情况是完全可以修复的(如果以正确的顺序完成)。 Snaggle 很容易通过一个简单的触发器来防止,检查左侧是否不 >= 右侧。按此顺序修复嵌套集,我得到了最好的结果。问题分解如下,SQL本身就不难了。

    • 交叉 (1:4 3:6) 或 (1:2 2:3)
    • 低于/高于 (1:4 1:3) 或 (1:4 2:4)
    • 间隙 (2:3 5:6 1:7) 或 (2:4 5:6 1:7)
    • 咬合 (2:1 4:2) 或 (1:1)

    【讨论】:

      猜你喜欢
      • 2011-04-07
      • 2014-01-13
      • 2010-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-29
      • 2011-09-04
      相关资源
      最近更新 更多