在 Postgresql 中限制基于 FK 的有向无环图的 CTE 搜索

Limiting CTE search based on FK for a Directed Acyclic Graph in Postgresql

我对原始 SQL 还是很陌生,之前在 ORM 中做过所有事情,这可能只需要额外一行 SQL.

在我的 Postgresql 数据库中,我有下表:nodes_tableedges_table 是非常标准的表用于在 Postgresql 数据库中定义图形(特别是 DAG)。

我还有一个 edges_group_table,它允许我在逻辑上将一堆边缘组合在一起。例如,如果图形是管道网络,则 edges_group_table 可用于指定哪些边在哪个建筑物中。

我有一个工作通用 Table 表达式 (CTE)(如下所示)来搜索给定节点的祖先节点。

因为图表可能很大,我希望能够减少 CTE 必须搜索的图表部分。除了指定起始节点外,我还希望能够指定一个 group_id 以便将 CTE 搜索限制在指定组中的那些边上。

Tables:

nodes_table
    id
    name

edges_table
    id
    name
    child_id -- a nodes_table id
    parent_id -- a nodes_table id
    group_id -- a edges_group_table id

edges_group_table
    id
    name

如何修改此 CTE 以将图的祖先搜索限制为来自 edges_group_table 的提供组内的那些边?

WITH RECURSIVE graph(id, depth) AS (
    SELECT first.parent_id, 1
        FROM edges_table AS first
        LEFT OUTER JOIN edges_table AS second
        ON first.parent_id = second.child_id
    WHERE first.child_id = 10 -- the node id we start from
UNION
    SELECT DISTINCT parent_id, graph.depth + 1
        FROM graph
        INNER JOIN edges_table
        ON edges_table.child_id = graph.id
)
SELECT id FROM graph
GROUP BY id
ORDER BY MAX(depth) DESC, id ASC

非常感谢对此的任何帮助!

在 CTE 的递归部分和第一个 select 子句中添加 WHERE 子句似乎应该很简单,假设您想限制这两个搜索:

WITH RECURSIVE graph(id, depth) AS (
    SELECT first.parent_id, 1
        FROM edges_table AS first
        LEFT OUTER JOIN edges_table AS second
        ON first.parent_id = second.child_id
            AND second.group_id = 15 --limit result for second node
    WHERE first.child_id = 10 -- the node id we start from
UNION
    SELECT DISTINCT parent_id, graph.depth + 1
        FROM graph
        INNER JOIN edges_table
        ON edges_table.child_id = graph.id
        WHERE edges_table.group_id = 15 --and all subsequent nodes
)
SELECT id FROM graph
GROUP BY id
ORDER BY MAX(depth) DESC, id ASC

请注意,在第一个表达式中,我们在 LEFT JOIN 部分使用过滤器而不是 WHERE 子句,这样即使第一条边没有连接到第二条边,它也会 return 一行设计的边缘组。