【问题标题】:Using MySQL query to traverse rows to make a recursive tree使用MySQL查询遍历行制作递归树
【发布时间】:2012-05-25 16:27:36
【问题描述】:

我有一个这样设置的物料清单表:
项目 - 父项

我显示物料清单的最终结果是这样显示的:

item 1  - parent 0    
    item 2 - parent 1    
    item 3 - parent 1    

最终的结果也可以是多层次的,像这样:

item 3 - parent 0    
    item 4 - parent 3    
    item 76 - parent 3    

它可以无限循环:

item 76 - parent 0    
    item 46 - parent 76    

item 46 - parent 0     
    item 25 - parent 46

现在,我要么只从数据库中获取 1 个级别:

SELECT * FROM bom WHERE parentId = $itemId (shorthand)

或者从表中提取每一行并使用我的递归函数来整理出我需要的那些,但这显然是低效的,因为我可能只需要 10 行,但我提取了 10,000 条记录。递归函数的输出只会创建一个像这样的树:

item 1
   item 2
   item 3
      item 4
      item 76
         item 46
            item 25

我只知道我从第 1 项开始。第 5 项可能有 11 个父项;他们不必按顺序进行。我想得到树中的所有子分支。我怎么能在mysql中做这个查询?

【问题讨论】:

    标签: mysql recursion


    【解决方案1】:

    AFAIK,用 MySQL 做到这一点并非易事。

    这里有一组很好的关于它的文章:

    http://explainextended.com/2009/03/17/hierarchical-queries-in-mysql/

    【讨论】:

    • 是的,我知道这不是一个基本问题。 :P 感谢您的文章。我一定会检查出来的。
    【解决方案2】:

    Bill Karwin 在 MySQL 中发布了关于 heirarchical data 的幻灯片。如果可以选择更改数据库设计,还有其他一些吸引人的方法来存储数据以使其更易于查询。他介绍的方法是:

    • 邻接列表
    • 路径枚举
    • 嵌套集
    • 闭包表

    幻灯片 69 有一张很好的表格,显示了每种方法的优缺点,因此我建议您先查看该幻灯片,了解哪种方法可能适合您,然后再返回查看如何实现它的详细信息。请注意,您选择的设计(邻接表)是唯一四种设计中的一种,它使查询子树变得困难。

    话虽如此,如果你不能改变你的设计或者你想坚持邻接列表,那么我不得不同意 Didier 的观点,你应该看看Quassnoi 的文章"Hierarchical queries in MySQL"。这是一篇非常清晰的文章,解释了如何高效地编写查询。

    【讨论】:

    • 很好的资源。我把它作为赏金来获取这样的信息。谢谢!
    • n^2 一个算不算?我的意思是,根据您的数据结构,该表将变得 EXPANSIVE ... 似乎左/右节点是最佳选择,但是您必须担心使用行插入进行索引和重新索引,对吧?
    【解决方案3】:

    早在 2011 年 10 月 24 日,有人发布了 question in the DBA StackExchange about tree traversal in MySQL。 MySQL 的 SQL 不支持。

    我在my answer to that question 中编写了三 (3) 个存储过程(GetParentIDByID、GetAncestry 和 GetFamilyTree)。希望这些信息可以帮助您构建您正在寻找的东西。

    【讨论】:

    • 优秀的程序。但随后SELECT id,GetFamilyTree(id) FROM pctable; 抛出错误:ERROR 1292 (22007): 截断不正确的 DOUBLE 值:'4,5'。我试图调试它,但徒劳无功。你有什么想法吗!谢谢
    【解决方案4】:

    MySQL (8) 现在支持递归查询。

    考虑到您的表项(id,父项)和 id = 1 的起始项,以下将完成这项工作:

    with recursive result(id, parent) as (select id, parent from item where id = 1 union all select i.id, i.parent from item i join result on i.parent = result.id) select * from result;
    

    【讨论】:

      猜你喜欢
      • 2012-06-15
      • 1970-01-01
      • 2018-07-12
      • 2014-03-11
      • 1970-01-01
      • 1970-01-01
      • 2015-08-26
      • 1970-01-01
      相关资源
      最近更新 更多