SQL 通过几种旨在表示父子关系的建模技术和查询方法来处理分层数据。最常见的方法包括邻接表(adjacency lists)、嵌套集(nested sets)、物化路径(materialized paths)和递归公用表表达式(recursive Common Table Expressions, CTEs)。每种方法在查询效率、维护便捷性和数据库系统支持方面都有其权衡。分层数据结构,如组织结构图或类别树,需要这些专门技术,因为传统的关联操作(例如,简单的连接)难以处理可变深度的关系。
一种广泛使用的方法是邻接表(adjacency list),其中每一行存储对其父节点的引用(例如,parent_id
列)。例如,一个 employees
表可能包含 employee_id
和 manager_id
列来表示报告层级。虽然实现简单,但查询多层深度的数据通常需要递归查询。PostgreSQL 的 WITH RECURSIVE
语法允许通过迭代地将表自身连接来遍历邻接表,直到处理所有层级。另一种方法是嵌套集模型(nested set model),它为每个节点分配数字范围(left
和 right
值)来表示其在树中的位置。这允许高效的子树查询(例如,WHERE node.left > parent.left AND node.right < parent.right
),但会使更新复杂化。物化路径(Materialized paths)将节点的完整路径存储为字符串(例如,/1/3/7/
),通过 LIKE
或专门的字符串函数实现模式匹配查询,尽管维护路径完整性可能容易出错。
方法的选择取决于用例需求。邻接表对于浅层层级来说很直观,但对于深度遍历效率不高。嵌套集优化了读密集型场景,但对于频繁更新来说很麻烦。物化路径对于固定深度查询工作良好,但难以处理重组。SQL Server、Oracle 和 PostgreSQL 等现代数据库支持递归 CTE,通过允许迭代遍历简化了对邻接表的查询。例如,WITH RECURSIVE cte AS (SELECT * FROM employees WHERE manager_id IS NULL UNION ALL SELECT e.* FROM employees e JOIN cte ON e.manager_id = cte.employee_id)
可以在一个查询中构建层级。开发者在选择方法时应优先考虑查询模式(例如,频繁的子树查找与更新)和数据库能力。