示例
WITH RECURSIVE
path(source, target, path_nodes, depth) AS (
-- 基本情况:直接连接
SELECT
source_id,
target_id,
source_id || ',' || target_id,
1
FROM relationships
WHERE source_id = ?
${relationshipType ? 'AND type = ?' : ''}
UNION ALL
-- 递归情况:通过中间节点连接
SELECT
p.source,
r.target_id,
p.path_nodes || ',' || r.target_id,
p.depth + 1
FROM path p
JOIN relationships r ON p.target = r.source_id
WHERE r.target_id NOT IN (SELECT value FROM (
SELECT CAST(value AS INTEGER) as value
FROM json_each('["' || REPLACE(p.path_nodes, ',', '","') || '"]')
))
AND p.depth < 10
${relationshipType ? 'AND r.type = ?' : ''}
)
SELECT path_nodes as path, depth
FROM path
WHERE target = ?
ORDER BY depth ASC
LIMIT 1;解释: 这段SQL代码示例展示了如何使用递归CTE(Common Table Expression)来查找图结构中的路径。它的主要用途是从一个节点到另一个节点找到一条路径,并记录路径上的所有节点以及路径的深度。
关键点解析:
-
WITH RECURSIVE: 这部分定义了一个递归CTE,名为
path。它由四列组成:source(起始节点),target(目标节点),path_nodes(路径上经过的节点,以逗号分隔表示),以及depth(路径深度)。 -
基本情况: 初始查询用于选择直接连接的关系,即从给定的
source_id到目标target_id的直接关系。在这里,路径仅包含源和目标节点,深度为1。 -
递归情况: 通过UNION ALL连接的第二个查询部分负责扩展路径。它通过与中间节点匹配来递归地构建更长的路径。对于每个当前存在的路径,它尝试找到额外可以连接到的新目标,但确保这些新目标不在当前已记录的路径中,以避免循环。
-
防止循环引用: 使用JSON函数
json_each将path_nodes列表解析为单独元素列表,并检查新的目标是否已经在该列表中存在。这种处理方式有效地防止了在图中创建环路。 -
限制条件和排序:
- 路径深度被限制在10以内,以避免过多计算。
- 最终选择的是达到指定目标且最短的那条路径,因为结果按深度升序排列并限制返回1条记录。
这种SQL语句适用于需要在数据库层面处理复杂关系型数据结构的问题场景,如社交网络分析、组织层级结构遍历等。