2

表结构

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 循环之后显示,但是从 starter id 1 开始循环,回复 id 为 0。

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

4

3 回答 3

3

有几种方法可以使层次信息更易于在 SQL 中使用:

  • 公用表表达式(根据 SQL-2003 标准)支持针对您正在使用的 parent-id 数据类型的递归 SQL 查询。到目前为止,MySQL 还不支持这个特性。PostgreSQL 8.4、Microsoft SQL Server 和 IBM DB2 是支持 CTE 语法的 RDBMS 品牌的示例。Oracle 还对支持递归查询的 SQL 语法进行了专有扩展。

  • 嵌套集(@phantombrain 提到的左/右解决方案)是 Joe Celko 的书“Smarties 中的树和层次结构”以及互联网上的大量文章和博客帖子中详细介绍的解决方案。

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

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

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

于 2009-08-11T00:47:28.813 回答
1

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

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

于 2009-08-11T00:14:43.487 回答
0

递归是最优雅的方法,但我认为 mySql 在自定义函数或存储过程中不支持它。我建议循环进入临时表或表变量以获取您的 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

希望有帮助

于 2009-08-11T00:48:49.113 回答