讲师中心 微信公众号
AI工具推荐 视频效率加速

如何利用SQL子查询实现父子级目录结构的层级查询?

阿敏同学_7314

阿敏同学_7314

发布时间:2026-06-16 13:23:19

|

162人浏览过

|

来源于php中文网

原创

递归CTE可查询无限层级目录结构,需表中含id和parent_id字段且根节点parent_id为NULL;PostgreSQL、SQL Server、SQLite 3.8.3+和MySQL 8.0+支持,旧版MySQL需应用层模拟。

如何利用sql子查询实现父子级目录结构的层级查询?

用 WITH RECURSIVE 查询无限层级目录结构

PostgreSQL、SQL Server、SQLite 3.8.3+ 和 MySQL 8.0+ 支持递归 CTE,这是查父子目录最直接的方式。不支持的数据库(如旧版 MySQL)必须用应用层拼接或多次查询模拟。

关键点在于:父节点和子节点必须在同张表里(比如 categories 表含 id 和 parent_id 字段),且根节点的 parent_id 为 NULL 或 0。

WITH RECURSIVE tree AS (
  SELECT id, name, parent_id, 1 AS level
  FROM categories
  WHERE parent_id IS NULL  -- 根节点
  UNION ALL
  SELECT c.id, c.name, c.parent_id, t.level + 1
  FROM categories c
  INNER JOIN tree t ON c.parent_id = t.id
)
SELECT * FROM tree ORDER BY level, id;
  • level 字段可用来缩进显示或限制深度(加 WHERE level )
  • MySQL 8.0+ 默认递归深度限制为 1000,超限会报错 ERROR 3636,需调大 cte_max_recursion_depth
  • PostgreSQL 中若出现循环引用(A→B→A),会报错 infinite recursion detected,建议加 cycle 子句(但不是所有数据库都支持)

MySQL 5.7 及更早版本只能靠多次 JOIN 模拟有限层级

没有递归 CTE 时,最多能查固定几级,比如三级目录就写三表 JOIN,四级就得四次 JOIN —— 不灵活,且容易漏数据或笛卡尔积爆炸。

典型写法是自连接,每层对应一次 LEFT JOIN:

SELECT 
  t1.name AS level1,
  t2.name AS level2,
  t3.name AS level3
FROM categories t1
LEFT JOIN categories t2 ON t2.parent_id = t1.id
LEFT JOIN categories t3 ON t3.parent_id = t2.id
WHERE t1.parent_id IS NULL;
  • 只适用于层级明确且稳定(比如“省-市-区”固定三级)
  • LEFT JOIN 是为了保留中间某层为空的情况(如一级目录下无二级)
  • 性能随 JOIN 数量指数下降,超过 4 层基本不可用;索引必须建在 parent_id 上,否则全表扫描
  • 无法返回统一字段结构(比如每行都是 id/name/level),前端解析麻烦

子查询嵌套写法只适合单路径追溯(比如查某个目录的全部祖先)

如果目标只是“给定一个 id,找出它所有上级目录”,用多层子查询比递归更兼容,也更易理解。

例如查 id = 100 的完整路径(从根到它自己):

SELECT * FROM categories
WHERE id IN (
  SELECT parent_id FROM categories WHERE id = 100
  UNION ALL
  SELECT parent_id FROM categories WHERE id IN (
    SELECT parent_id FROM categories WHERE id = 100
  )
  UNION ALL
  SELECT parent_id FROM categories WHERE id IN (
    SELECT parent_id FROM categories WHERE id IN (
      SELECT parent_id FROM categories WHERE id = 100
    )
  )
);
  • 这种写法本质是手动展开递归,层数完全由 SQL 长度决定,维护成本高
  • 不能保证顺序(谁是第一级谁是第二级),需要额外用 ORDER BY 或应用层排序
  • 比起 WITH RECURSIVE,它无法自然表达“向下找子节点”,只适合向上溯源
  • Oracle 用户可能习惯用 CONNECT BY PRIOR,但那是方言,跨库不可移植

应用层组装仍是很多团队的实际选择

当数据库不支持递归、层级动态变化、或需配合权限过滤时,一次性查出全部目录再用代码组装树结构,反而更可控。

核心思路:一次 SELECT * 拿全量,然后按 parent_id 建哈希映射,遍历构建树:

// 伪代码示例(Python)
rows = db.execute("SELECT id, name, parent_id FROM categories")
nodes = {r['id']: {'id': r['id'], 'name': r['name'], 'children': []} for r in rows}
roots = []
for r in rows:
    if r['parent_id'] is None:
        roots.append(nodes[r['id']])
    else:
        nodes[r['parent_id']]['children'].append(nodes[r['id']])
  • 比多次查询快,比复杂 SQL 更易 debug
  • 可轻松加入业务逻辑:比如跳过被禁用的节点、按用户权限裁剪分支
  • 注意空 parent_id 类型:有的库存 NULL,有的存 0,代码要对齐
  • 如果目录量极大(10 万+ 行),内存和序列化开销需评估,此时还是得回数据库做分层加载

实际项目里,递归 CTE 是首选,但得确认数据库版本和运维是否允许开启相关参数;老系统迁移到新版本前,应用层组装往往是最省事的过渡方案。真正容易被忽略的是循环引用检测——测试数据随手设错一个 parent_id,就能让整个树查询卡死或报错。

热门AI工具

更多
PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

UP简历
UP简历 Hot

一款AI办公效率工具,主要用于基于AI技术的免费在线简历制作工具,适合需要提升相关任务效率的用户。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

音述AI
音述AI Hot

一款AI音频处理工具,主要用于音述AI是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

3883

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

831

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

1009

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

5721

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2663

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

5700

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

7521

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

1030

2024.04.29

LLVM自定义Pass怎么写
LLVM自定义Pass怎么写

本专题聚焦LLVM自定义Pass开发,整理Pass类结构、run()方法、PreservedAnalyses、CMake构建、插件注册、-load-pass-plugin加载和测试用例编写流程。

0

2026.09.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn