如何使用SQL嵌套查询进行父子层级查询_利用路径编码与子查询匹配

落辰大大_6574

落辰大大_6574

2026-05-08

673人浏览

原创

路径编码查询需谨慎:like匹配祖先须规范路径格式且难走索引;查直接子节点优先用parent_id外键;存在性判断用exists优于in;递归查树必须用with recursive,子查询无法真正递归。

如何使用sql嵌套查询进行父子层级查询_利用路径编码与子查询匹配

WHERE 子句里的子查询能做父子层级查询,但直接靠它“匹配路径编码”容易掉坑——因为标准 SQL 的嵌套查询本身不维护树结构上下文,IN 或 = 只能做值匹配,不能天然表达“前缀包含”或“层级继承”关系。真要靠路径编码(如 '/1/5/12/')查祖先或后代,得手动拼字符串逻辑,且必须配合函数支持。

路径字段里用 LIKE 做祖先匹配

假设你有一张 category 表,含 id、name、path(存类似 '/1/5/12/' 的字符串),想查 ID=12 的所有祖先节点:

  • path 字段必须以斜杠开头和结尾,否则 LIKE 容易误匹配(比如 '/12/' 会错中 '/112/')
  • 写法是:SELECT * FROM category WHERE '/1/5/12/' LIKE CONCAT(path, '%')
  • 注意:这个查询无法走 path 字段的普通 B-Tree 索引,除非用函数索引(MySQL 8.0+ 支持 CREATE INDEX idx_path ON category ((SUBSTRING_INDEX(path, '/', -2))) 这类表达式索引)
  • PostgreSQL 用户可考虑 ltree 扩展,原生支持路径操作符 @>(包含)和 (被包含)

用子查询查直接子节点(非递归)

如果只要查某节点的**直接子节点**(即父 ID 明确),根本不需要路径编码,用外键字段更高效:

智谱清言
智谱清言

智谱清言是一款AI工具,智谱推出的全能AI助手。

下载
  • 假设表有 parent_id 字段,则查 ID=5 的子节点: SELECT * FROM category WHERE parent_id = 5
  • 若坚持用路径字段反推(比如没有 parent_id),可这样写子查询:SELECT * FROM category c1 WHERE c1.path LIKE (SELECT CONCAT(path, '%') FROM category c2 WHERE c2.id = 5) AND LENGTH(c1.path) > LENGTH((SELECT path FROM category c3 WHERE c3.id = 5))
  • 这个写法性能差:子查询执行多次(取决于优化器是否物化),且 LENGTH + LIKE 组合几乎无法索引加速
  • 更糟的是,它会把“孙子”也当“子节点”返回,必须额外加层级判断(比如统计斜杠数量),SQL 就开始变味了

EXISTS 比 IN 更适合存在性判断

当你要查“哪些分类下有商品”,且分类表和商品表通过路径关联(例如商品表有个 category_path 字段),别用 IN 套子查询:

  • 错误示范:SELECT * FROM category WHERE path IN (SELECT DISTINCT category_path FROM product) —— 若 category_path 为 NULL,整行被丢弃;IN 对空集返回空结果,不是 false
  • 推荐用 EXISTS:SELECT * FROM category c WHERE EXISTS (SELECT 1 FROM product p WHERE p.category_path LIKE CONCAT(c.path, '%'))
  • EXISTS 在找到第一行就短路,比 IN 先生成完整结果集再比较更省资源
  • 仍需注意:这里 LIKE 的右值是动态拼接的,多数数据库无法对 p.category_path 使用索引,除非你建了函数索引或改用前缀字段(如 ancestor_ids 数组)

真正需要递归时,别硬扛子查询

路径编码本质是扁平化树结构,但“查所有后代”“查到根路径”这类需求,标准嵌套子查询最多模拟 2–3 层,再深就不可维护:

  • MySQL 8.0+、PostgreSQL、SQL Server 都支持 WITH RECURSIVE,这才是查树的正解
  • 例如查 ID=12 的所有祖先:WITH RECURSIVE tree AS (SELECT id, parent_id, name, path FROM category WHERE id = 12 UNION ALL SELECT c.id, c.parent_id, c.name, c.path FROM category c INNER JOIN tree t ON c.id = t.parent_id) SELECT * FROM tree
  • 子查询做不到递归展开,强行多层嵌套(比如三层 IN 套娃)不仅难读,还可能触发 32 层限制,且无法动态控制深度
  • 如果数据库不支持递归 CTE,优先考虑在应用层分步查,或者加冗余字段(如 root_id、level)预计算

路径编码 + 子查询看似轻量,实则暗藏索引失效、语义模糊、层级失控三重风险。真要查父子关系,先看数据库版本是否支持 WITH RECURSIVE;不支持的话,宁可用两三个简单查询换清晰性和可维护性。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

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

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

2023.10.12

3863

8

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

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

2023.10.27

831

4

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

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

2024.02.23

1009

5

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

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

2024.03.06

5701

10

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

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

2024.03.06

2643

4

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

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

2024.04.07

5680

11

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

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

2024.04.29

7481

6

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

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

2024.04.29

1030

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

892

5

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Fitten Code官方手册
Fitten Code官方手册

共0课时 | 0人学习

CodeGeex使用手册
CodeGeex使用手册

共0课时 | 0人学习

通义灵码手册
通义灵码手册

共0课时 | 0人学习