示例

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_eachpath_nodes 列表解析为单独元素列表,并检查新的目标是否已经在该列表中存在。这种处理方式有效地防止了在图中创建环路。

  • 限制条件和排序:

    • 路径深度被限制在10以内,以避免过多计算。
    • 最终选择的是达到指定目标且最短的那条路径,因为结果按深度升序排列并限制返回1条记录。

这种SQL语句适用于需要在数据库层面处理复杂关系型数据结构的问题场景,如社交网络分析、组织层级结构遍历等。