mysql查询树形,id与pid关联实践

 更新时间:2026年06月05日 10:04:03   作者:hefeng_aspnet  
在MySQL中查询基于id和pid关联的树形结构数据,推荐使用递归公用表表达式(WITH RECURSIVE)以实现高效递归查询,适用于MySQL8.0及以上版本,对于旧版本MySQL,可使用自定义函数收集所有节点或父节点ID,或采用应用层组装策略,一次性加载数据并内存组装树形结构

在MySQL中查询基于id和pid关联的树形结构数据,主要有以下几种常用方案,可根据MySQL版本及业务需求选择:

1. 使用递归公用表表达式(推荐 MySQL 8.0+)

这是最标准且性能较好的方式,利用 WITH RECURSIVE语法实现递归查询。

‌查询指定节点的所有子级(向下查询):

WITH RECURSIVE tree_cte AS (
    -- 锚点成员:指定起始节点
    SELECT id, pid, name, 1 as level
    FROM tree
    WHERE id = 1  -- 替换为指定的父节点ID
    UNION ALL
    -- 递归成员:查找子节点
    SELECT t.id, t.pid, t.name, tc.level + 1
    FROM tree t
    INNER JOIN tree_cte tc ON t.pid = tc.id
)
SELECT * FROM tree_cte;

查询指定节点的所有父级(向上查询):

WITH RECURSIVE parent_cte AS (
    -- 锚点成员:指定起始节点
    SELECT id, pid, name
    FROM tree
    WHERE id = 5  -- 替换为指定的子节点ID
    UNION ALL
    -- 递归成员:查找父节点
    SELECT t.id, t.pid, t.name
    FROM tree t
    INNER JOIN parent_cte pc ON t.id = pc.pid
)
SELECT * FROM parent_cte;

2. 使用自定义函数(适用于 MySQL 5.7及以下)

在旧版本MySQL中,通常通过创建存储函数,利用循环和 FIND_IN_SET 或 GROUP_CONCAT 来收集所有子节点或父节点的ID字符串,然后再进行查询。

‌获取所有子节点ID的函数示例逻辑:‌

  • 初始化一个包含根节点ID的字符串变量。
  • 循环查询当前层级所有节点的子节点ID。
  • 将新发现的子节点ID拼接到字符串中。
  • 直到没有新的子节点产生为止。
  • 返回ID字符串,外层使用 FIND_IN_SET(id, get_child_ids(root_id)) 进行过滤。

注意:这种方法在数据量较大时性能较差,且受限于 group_concat_max_len 系统变量。

3. 应用层组装(通用方案)

如果数据库查询压力较大或逻辑复杂,可以采用“一次加载,内存组装”的策略:

3.1 SQL查询‌:一次性查询出所有相关节点(或全表),按 pid 或 level 排序。

SELECT * FROM tree ORDER BY pid, id;

‌3.2 代码处理‌:在Java/Python/Go等后端语言中,遍历列表,利用Map将节点挂载到对应的父节点下。

  • 创建一个 Map<ID, Node>。
  • 遍历所有节点,将节点放入Map。
  • 再次遍历,根据 pid 从Map中找到父节点,将当前节点加入父节点的 children 列表。  
  • 筛选出根节点(pid为0或null)作为树的入口。

4. 其他高级设计模式(针对高性能需求)

如果树形结构非常深且查询频繁,可以考虑改变表结构设计:

  • 路径枚举(Path Enumeration)‌:增加 path 字段(如 0,1,5,10),查询子节点时使用 LIKE '0,1,%'。
  • 闭包表(Closure Table)‌:新建一张关系表,存储所有祖先-后代关系对,查询时直接Join该表,效率极高但维护成本稍高。
  • 嵌套集(MPTT)‌:增加 lft 和 rgt 字段,通过范围查询获取子树,读取性能极佳,但插入和移动节点时需要更新大量数据。

总结建议‌

如果是 ‌MySQL 8.0+‌,优先使用 ‌方案1(WITH RECURSIVE)‌,语法简洁且由数据库引擎优化。

如果是 ‌MySQL 5.7‌ 且数据量小,可使用 ‌方案2(自定义函数)‌。

如果数据量大且业务逻辑复杂,推荐 ‌方案3(应用层组装)‌,减少数据库递归压力。

如果对读取性能有极致要求且写操作较少,考虑 ‌方案4(闭包表或路径枚举)‌。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • mysql格式化小数保留小数点后两位(小数点格式化)

    mysql格式化小数保留小数点后两位(小数点格式化)

    今天遇到一个问题,格式化浮点数的问题,用format(col,2)保留两位小数点,出现一个问题,例如下面的语句,后面我们给出解决方法
    2013-12-12
  • mysql 8.0.25 安装配置方法图文教程

    mysql 8.0.25 安装配置方法图文教程

    这篇文章主要为大家详细介绍了mysql 8.0.25 安装配置方法图文教程,文中安装步骤介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • Mysql查询列横向转换逗号拼接并加上双引号

    Mysql查询列横向转换逗号拼接并加上双引号

    使用Mysql的GROUP_CONCAT函数和CONCAT函数,将查询结果的列横向转换为逗号拼接的字符串,并在每个值周围加上双引号,最终结果每一行包含一个user_id和一个由双引号括起来的user_names字段,本文介绍Mysql查询列横向转换逗号拼接并加上双引号的知识,感兴趣的朋友一起看看吧
    2025-02-02
  • MySQL中的常用函数及用法总结

    MySQL中的常用函数及用法总结

    MySQL是一种常用的关系型数据库管理系统,它提供了许多内置函数来处理数据,本文将介绍MySQL中的各种常用函数,包括字符串函数、日期函数、数学函数、聚合函数等,需要的朋友可以参考下
    2023-06-06
  • Mysql 5.6.37 winx64安装双版本mysql笔记记录

    Mysql 5.6.37 winx64安装双版本mysql笔记记录

    机器上现在已经存在5.0版本MySQL的情况下装一个最新版的mysql,下文通过实例代码给大家介绍Mysql 5.6.37 winx64安装双版本mysql笔记记录,感兴趣的朋友一起看看吧
    2017-07-07
  • Ubuntu系统安装mysql超详细步骤

    Ubuntu系统安装mysql超详细步骤

    这篇文章主要给大家介绍了关于Ubuntu系统安装mysql的相关资料,现在的软件越来越好安装,尤其是在ubuntu下安装软件,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-09-09
  • MySQL 数据库铁律(小结)

    MySQL 数据库铁律(小结)

    这篇文章主要介绍了MySQL 数据库铁律,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • mysql 5.7.16 ZIP包安装配置教程

    mysql 5.7.16 ZIP包安装配置教程

    这篇文章主要为大家详细介绍了mysql 5.7.16 ZIP包安装配置教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-08-08
  • 浅析MySQL如何实现百万级数据的高效查询

    浅析MySQL如何实现百万级数据的高效查询

    在当下的数据库技术背景下,处理 MySQL 百万级数据的查询需要综合考虑数据库设计、查询优化、硬件配置和高级技术,下面我们就来看看具体的实现方案吧
    2025-07-07
  • Win7 64位 mysql 5.7下载安装常见问题小结

    Win7 64位 mysql 5.7下载安装常见问题小结

    这篇文章主要介绍了Win7 64位 mysql 5.7下载安装常见问题小结,本文图文并茂给大家介绍的非常详细,需要的朋友参考下吧
    2017-06-06

最新评论