2021-10-12 18:14:41
SQL的递归查询是通过WITH RECURSIVE语法实现的,用于处理不定深度的层级数据结构(如组织架构、BOM等),通过锚成员定义初始数据集,递归成员引用自身逐步遍历层级,并用UNION ALL合并结果,最终构建完整的层级关系或路径。
WITH RECURSIVE的实现方法语法结构基本形式为:
WITH RECURSIVE cte_name AS ( -- 锚成员(Anchor Member):定义初始数据集 SELECT ... FROM base_table WHERE initial_condition UNION ALL -- 或 UNION -- 递归成员(Recursive Member):引用CTE自身,逐步生成新行 SELECT ... FROM another_table t JOIN cte_name r ON t.join_column = r.join_column WHERE recursive_condition)SELECT ... FROM cte_name;关键组成部分
锚成员:独立的SELECT语句,不引用CTE自身,定义递归起点(如顶层经理)。
递归成员:引用CTE自身的SELECT语句,通过JOIN操作连接CTE与表数据,生成下一层级数据。
终止条件:递归成员的WHERE子句需限制新行生成,防止无限循环(如e.manager_id无对应值时停止)。
UNION ALL vs. UNION:
UNION ALL保留所有行(包括重复),适用于需要完整路径的场景。
UNION去重,但性能开销更高,仅在需要唯一结果时使用。
路径追踪与深度限制
路径记录:通过CAST(... AS VARCHAR(MAX))累积路径信息(如path || ' -> ' || e.employee_name)。
深度控制:添加level列记录递归深度,并在WHERE子句中限制最大深度(如AND eh.level < 10)。
循环检测:
手动方式:在路径中记录已访问节点,递归时检查是否重复。
数据库支持:如PostgreSQL的CYCLE子句可自动检测循环。
说明:
索引优化
为连接列(如employee_id、manager_id)和WHERE条件列建立索引,加速JOIN操作。
限制初始数据集
缩小锚成员范围(如从特定部门开始),减少递归起点数据量。
避免冗余列
仅选择必要列,减少递归过程中传递的数据量。
循环与深度控制
使用level列限制递归深度,或通过路径检查避免循环。
数据库特性利用
不同DBMS对WITH RECURSIVE的实现可能不同(如PostgreSQL支持CYCLE),需查阅文档调整语法。
性能监控
使用EXPLAIN ANALYZE分析执行计划,识别瓶颈(如全表扫描、低效JOIN)。
通过合理设计锚成员、递归成员和终止条件,并结合索引优化与深度限制,WITH RECURSIVE能高效解决传统自连接难以处理的复杂层级问题。