在MySQL中是否有`connect by`替代方案?

时间:2013-10-02 08:11:20

标签: mysql sql oracle

如果我使用Oracle,则可以使用connect by关键字来创建分层查询。目前我正在项目中使用MySQL,我想知道MySQL中是否有connect by的替代方案?

我试过谷歌但到目前为止无济于事。我想要实现的是通过一个查询从数据库中获取树。涉及两个表:

areasarea_to_parent_join。后者包含两个ID,一个是area_id,另一个是parent_id。所以它基本上是一个自我连接,我可以使用该模型创建图形。事实上,它目前仅用于创建树木,但未来可能会发生变化。但在任何一种情况下,我想拥有的只是一棵生成树。

修改: areas可能有超过1.000.000条记录,这使得大多数空间密集型选项都无法实现。

2 个答案:

答案 0 :(得分:8)

正如评论中所说,mysql没有一个简短的方法。

<强> BUT!

如果您可以更改数据库结构,则可以部署更好的设计来处理树状层次结构。

如果您关注Bill Karwin的 THIS TUTORIAL HERE 是引用该幻灯片教程的原始答案),您可以找到4种方法用于建模层次结构:

  1. Adiacency List
  2. 路径枚举
  3. 嵌套集
  4. 关闭表
  5. 现在,最好的模型可能是第4个(我将其他3个模型的描述留给读者),它基本上需要2个表:一个用于元素,一个用于路径。在路径表(闭包表本身)中,您将存储从每个节点到每个后代的每条路径(不仅仅是直接子节点!)。

    建议同时保存每行的路径长度,因为它可以更容易地查询树中的直接子项。

    即使此解决方案需要更多空间,它也具有最佳的整体性能并且使用起来非常简单:它完全不依赖于递归查询而且它将为整个数据集赋予参照完整性!

    例如,要获取节点#4的每个孩子:

    select a.*
    from nodes a
    join paths b
    on a.node_id = b.descendant
    where b.ancestor = 4
    

    另一个例子:获取节点#11的所有祖先

    select a.*
    from nodes a
    join paths b
    on a.node_id = b.ancestor
    where b.descendant = 11
    

    需要删除节点#6的子树

    delete from paths where descendant in
    (select descendant from paths where ancestor = 6)
    

答案 1 :(得分:1)

在我的应用程序中,我很少需要请求整个子树。因此,为了摆脱o2的大问题,我使用3-deep关联/闭包表查找 - 用祖先填充表格 - 仅为子,父和祖父母填充后代。只要认识到你得到的东西 - 即没有存储过程就不要查询整个树。