复杂的sql树行

时间:2009-08-11 00:09:45

标签: mysql sql hierarchical-data

表格结构

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 个答案:

答案 0 :(得分:3)

在SQL中,有几种方法可以更容易地使用分层信息:

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

  • 嵌套集(@phantombrain提到的左/右解决方案)是Joe Celko的书“用于Smarties的SQL中的树和层次结构”中详细介绍的解决方案,还有许多文章和博客在互联网上张贴。

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

  • 关闭表(又名传递关闭关系)使用第二个表来存储所有祖先 - 后代关系,而不仅仅是您正在使用的设计中的直接父关系。一旦存储了所有路径,许多类型的查询就会变得更容易。

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

答案 1 :(得分:1)

假设这些是菜单项而不是非常动态的东西,例如论坛,我建议更改架构以为每个项添加左右值。左侧和右侧值之间的ID都是您要查询的节点的子级。因此,很容易做一个查询来获取左/右值,第二个查询来获取子项。

有关详细信息,请参阅http://www.sitepoint.com/print/hierarchical-data-database/

答案 2 :(得分:0)

递归是最优雅的方法,但我认为mySql不支持自定义函数或storedprocedures。我建议循环进入临时表或表变量以获取您的ID,然后加入表并查询结果。我不太了解mySql,所以这是未经测试的,但这是有效的。

CREATE TEMPORARY TABLE tbl (myid int, ViewOrder int); 
Set @ifoundID=IdYourLookingFor;
Set @iStartID=@ifoundID;
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 id=@ifoundID; --find the next id
  SET @iOrder1=@iOrder-1; --increment the order
  INSERT INTO tbl(myid,ViewOrder)VALUES(@ifoundID,@iOrder);--save the nextid
 END WHILE;
END

Set @ifoundID=@iStartID;
BEGIN --get the ones going down
 WHILE (@ifoundID Is Not Null) DO 
  SELECT @ifoundID=id FROM YourTable WHERE reply_id=@ifoundID; --find the next id
  SET @iOrder1=@iOrder+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

希望有所帮助