2009-08-11 23 views
2

表结构复杂的SQL树行

id | message | reply_id 
1  | help me! | 0 
434 | love to | 1 
852 | didn't work | 434 
0110 | try this | 852 
2200 | this wont | 0 
5465 | done. :) | 0110 

我有一个ID为“852”,这是树形菜单的中间,但我想以前所有的相关的和未来相关行,所以我希望得到以下结果是这样的:

帮帮我! >爱到>没有工作>尝试这个>完成。 :)(这个结果表明在php循环之后,但是从启动器id 1开始循环,并且回复id为0.

注意:2200 id没有显示在结果中,因为它不是组的一部分。

回答

3

有几种备选方案制作分层信息更容易在SQL一起工作:

  • 通用表表达式(每个SQL-2003标准),支持对父-ID类型的递归SQL查询你正在使用的数据。到目前为止,MySQL不支持这个功能。 PostgreSQL 8.4,Microsoft SQL Server和IBM DB2是支持CTE语法的RDBMS品牌的示例。 Oracle对SQL语法也有一个专有的扩展,支持递归查询。

  • 嵌套集合(即@phantombrain提到了左/右的解决方案)是“在SQL树木和层次结构聪明豆”乔Celko的书中详细介绍,并在互联网上的许多文章和博客文章的解决方案。

  • 路径枚举(aka Materialized Path)在层次结构的每一行中存储一个字符串,以记录该行的祖先路径。将此与LIKE查询结合使用,可以将路径字符串与其祖先路径和后代路径进行比较。

  • 关闭表(又名传递闭包的关系)使用第二表的所有祖先子孙关系,而不仅仅是直接父存储为您所使用的设计。一旦存储了所有路径,许多类型的查询就变得更加容易。

  • 混合解决方案也存在。例如,存储正在做的直接父级ID,但也存储树的根。现在,您可以在同一层次结构中获取所有其他行,将它们提取到应用程序代码中,然后使用常规数据结构对树进行分类。

+0

我喜欢你的混合解决方案。我实际上认为同样的解决方案来拉组ID(parent_id),但做一个API,并要求用户发回组ID与答复ID,我不认为这将是一个好主意,但我们可以做到这一点,而无需询问用户和拉ID而不问。不能我们拉参考行?对于mysql来说真的很难吗? 拉动当前行的下一行或前一行,id是wired(id:xcwevesd)..所以不能用整数。 – Basit 2009-08-11 01:29:52

+0

我没有遵循这一切。但FWIW这不是MySQL问题,这是一个SQL语言问题。如果没有SQL2003中引入的CTE语法,当您使用“parent-id”(也称为邻接列表)设计时,没有简单的方法来执行递归查询来获取整个树。这就是为什么人们想出了另一种存储层次结构的方法。 – 2009-08-11 02:26:25

+0

即时尝试做以下,我认为它是一个很好的解决方案http://www.nabble.com/tree-query-td6357375.html,但它给出以下错误http://stackoverflow.com/questions/1267172/mysql-分隔符错误 – Basit 2009-08-12 17:20:43

1

假设这些是菜单项而不是非常动态的东西,比如论坛,我会推荐一个模式更改为每个项目添加左值和右值,左值和右值之间的ID都是节点的子节点您正在查询,因此,可以轻松地执行一个查询以获取左/右值,并通过第二个查询获取子项目。

+0

它的一个论坛/邮件,butn的菜单项。但我实际上也想用它作为菜单项目..但是这个解决方案我已经在做“邻接表模型”(我不推荐它,但我没有任何其他解决方案)。我需要同样的消息,但一个查询,并不需要做很多更新。 即时通讯制作类似twitter的东西..如果我们得到很多很多的推文并且更新它们会是个坏主意,那么循环就不是好主意。任何解决方案!? – Basit 2009-08-11 01:25:03

0

递归是最优雅的方式来做到这一点,但我不认为mySql支持自定义函数或存储过程。我建议将一个循环放入临时表或表变量中以获取您的ID,然后加入表并查询结果。我不太了解mySql,所以这是未经测试的,但是有这个效果。

CREATE TEMPORARY TABLE tbl (myid int, ViewOrder int); 
Set @ifoundID=IdYourLookingFor; 
Set @[email protected]; 
Set @iOrder=0; 
INSERT INTO tbl(myid,ViewOrder)VALUES(@ifoundID,@iOrder); 

BEGIN --get the ones going up 
WHILE (@ifoundID Is Not Null) DO 
    SELECT @ifoundID=reply_id FROM YourTable WHERE [email protected]; --find the next id 
    SET @[email protected]; --increment the order 
    INSERT INTO tbl(myid,ViewOrder)VALUES(@ifoundID,@iOrder);--save the nextid 
END WHILE; 
END 

Set @[email protected]; 
BEGIN --get the ones going down 
WHILE (@ifoundID Is Not Null) DO 
    SELECT @ifoundID=id FROM YourTable WHERE [email protected]; --find the next id 
    SET @[email protected]+1; --increment the order 
    INSERT INTO tbl(myid,ViewOrder)VALUES(@ifoundID,@iOrder);--save the nextid 
END WHILE; 
END 

SELECT * FROM tbl INNER JOIN YourTable ON tbl.myid=YourTable.id ORDER BY ViewOrder 

希望帮助

+0

mysql支持自定义函数,但其​​写入方式不同,不知道我们将如何写入mysql。 – Basit 2009-08-12 17:23:24