【问题标题】:MySQL: Get all subcategories, descendantsMySQL:获取所有子类别,后代
【发布时间】:2009-11-07 06:46:43
【问题描述】:

我将 mysql 表定义为:

类别:category_id、category_name、parent_category_id

我正在寻找一个很好的 sql 查询,它可以检索给定 category_id 的所有 DESCENDANTS。这意味着,它的孩子,以及它的孩子的孩子。

如果有帮助,我们可以假设最大级别数 (3)。此查询可以在任何级别(根、级别 2、级别 3)发送。

谢谢!

内森

【问题讨论】:

    标签: mysql


    【解决方案1】:

    有几种方法可以将树存储在数据库中。有一篇关于 sitepoint 的精彩文章描述了所有技术:

    http://articles.sitepoint.com/article/hierarchical-data-database/2

    如果您希望能够在一次查询中获取树的整个部分,最合适的方法是修改前序树遍历。

    这种技术也称为嵌套集。如果您想了解更多关于该主题的文献,这里有更多信息:

    http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

    【讨论】:

    • 使用现有结构怎么样?
    • 使用您当前的表结构,您必须使用递归查询。
    【解决方案2】:

    可以在单个查询和一段递归后端代码逻辑中完成:Formatting a multi-level menu using only one query

    如果您也使用PHP,本文附带一个PHP 示例作为奖励,但翻译成另一种语言并不难。由于您没有提及您使用的服务器端语言,因此我无法提供任何提示。

    希望这会有所帮助。

    【讨论】:

      【解决方案3】:

      如果您想使用最多 3 个级别的结构,您可以将表连接到自身 3 次:

      SELECT 
          c1.id AS level_1, 
          c2.id AS level_2, 
          c3.id AS level_3
      FROM categories c1
      LEFT JOIN categories c2 ON c1.id = c2.parent_id
      LEFT JOIN categories c3 ON c2.id = c3.parent_id
      WHERE c1.parent_id IS NULL
      

      我假设,父类别的 parent_id 为 NULL。

      一些例子:

      DECLARE @categories TABLE 
      (
          id INT,
          parent_id INT
      )
      
      INSERT INTO @categories(id,parent_id) VALUES(1,NULL)
      INSERT INTO @categories(id,parent_id) VALUES(4,1)
      INSERT INTO @categories(id,parent_id) VALUES(5,1)
      INSERT INTO @categories(id,parent_id) VALUES(6,5)
      INSERT INTO @categories(id,parent_id) VALUES(2,NULL)
      
      SELECT * FROM @categories
      
      SELECT c1.id AS level_1, c2.id AS level_2, 
          c3.id AS level_3
      FROM @categories c1
      LEFT JOIN @categories c2 ON c1.id = c2.parent_id
      LEFT JOIN @categories c3 ON c2.id = c3.parent_id
      WHERE c1.parent_id IS NULL
      

      返回:

      level_1 | level_2 | level_3
      ---------------------------
      1       | 4       | NULL
      1       | 5       | 6
      2       | NULL    | NULL
      

      【讨论】:

      • 我喜欢你用这个得到的地方,除了最终格式不是很容易使用(然后整个查询将用作子查询,例如 WHERE categoryId IN (list调用后代)。我们能否进行查询,生成一个缓存表,该表将包含以下列:parent_category_id,descendant。它将列出每个给定类别的所有后代?
      • 这不是一个解决方案,只是一个补丁,因为通常情况下我们无法预测类别级别。而且,至少,硬编码它是非常糟糕的。
      • @Lambrusco 在回答 7 年后哇哦。关心给出适当的解决方案?
      • @LukaszLysik 抱歉,我没有完整阅读这个问题,我们可以接受只使用三个级别。对于多级解决方案,我们可以根据父id递归选择子类别,也可以全部选择然后递归遍历,解决方案在这里stackoverflow.com/questions/2398402/…
      • @Lambrusco 你为什么要挖出老问题,发表完全无用的评论,然后投票否决答案?
      【解决方案4】:

      MySQL 不支持递归查询,但您可以使用带有 WHILE 循环的存储过程查找所有后代。请参阅此book sampleThe edge list 部分。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-30
        • 2011-07-30
        • 1970-01-01
        • 2012-12-26
        • 1970-01-01
        • 2014-01-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多