表格结构
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未显示在结果中,因为它不属于该组。
答案 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
希望有所帮助