【问题标题】:How to fetch categories and sub-categories in a single query in sql? (mysql)如何在sql中的单个查询中获取类别和子类别? (mysql)
【发布时间】:2026-02-15 01:30:02
【问题描述】:

我想知道是否可以在单个数据库提取中提取类别和子类别。

我的数据库表与下面显示的类似

表格

cat_id parent_id
1      0
2      1
3      2
4      3
5      3
6      1

即当输入为 3 时,应获取 parent_id 为 3 的所有行和第 3 行本身以及第 3 行的所有父项。

输出

cat_id parent_id
3      2   -> The row 3 itself
4      3   -> Row with parent as 3
5      3   -> Row with parent as 3
2      1   -> 2 is the parent of row 3
1      0   -> 1 is the parent of row 2

这可以使用存储过程和循环来完成吗?如果是这样,它将是单个数据库提取还是多个?或者还有其他更好的方法吗?

谢谢!!!

【问题讨论】:

  • 这里有一些内容:dev.mysql.com/tech-resources/articles/hierarchical-data.html 在 MySQL 中,这是一个很难的主题...
  • 谢谢伙计。确实不错的文章!所以,我的遵循相邻的模型!?嗯...但是由于级别可以变化(可以在表格中进行动态条目),我仍然不确定如何实现它。还在想……
  • 2天后仍然卡住! :( 对结果不满意!!!
  • 相邻模型和嵌套集合模型的组合给了我完美的菜单! :-)

标签: sql mysql stored-procedures


【解决方案1】:

如果您询问“mysql 递归查询中是否存在?”回答“否”。

但是有很好的方法来处理它。

创建辅助表(比如 CatHierarchy)

CatHierarchy:
    SuperId, ChildId, Distance
------------------------------ 
     1          1         0
     1          2         1
     2          2         0

此冗余数据允许在 1 个查询中轻松选择任何层次结构,并在 2 个插入中支持任何层次结构(删除也可以在 1 个查询中执行删除级联完整性的帮助)。

那么这是什么意思。您跟踪层次结构中的所有路径。 Cat 的每个节点都必须添加对自身的引用(距离为 0),然后通过添加有关节点链接的冗余数据来支持复制。

要使用 sub 选择类别,只需编写:

 SELECT c.* from Category c inner join CatHierarchy ch ON ch.ChildId=c.cat_id
      WHERE ch.SuperId = :someSpecifiedRootOfCat

someSpecifiedRootOfCat - 是指定类别根的参数 就是这样!

【讨论】:

    【解决方案2】:

    Sitepoint 上有一篇非常好的文章 - 尤其是 Modified Preorder Tree Traversal

    【讨论】:

      【解决方案3】:

      这很棘手。我假设您想显示类别,有点像文件夹视图?三个字段:MainID、ParentID、Name... 应用于您的表,它应该像一个魅力一样工作。我觉得这叫递归查询?

      WITH CATEGORYVIEW (catid, parentid, categoryname) AS
      (
      SELECT catid, ParentID, cast(categoryname as varchar(255))
        FROM [CATEGORIES]
       WHERE isnull(ParentID,0) = 0
      
      UNION ALL
      
      SELECT C.catid, C.ParentID, cast(CATEGORYVIEW.categoryname+'/'+C.categoryname as varchar(255))
        FROM [CATEGORIES] C
        JOIN CATEGORYVIEW ON CATEGORYVIEW.catID = C.ParentID
      )
      SELECT * FROM CATEGORYVIEW ORDER BY CATEGORYNAME
      

      【讨论】: