使用递归 CTE 找到最终 parents

finding ultimate parents with recursive CTE

我有一个 SQLite table 的 child 个 ID 及其 parent 个 ID。其中给定的 parent 也可能出现在 child 列中。例如:

child    parent
-----    ------
3        4
2        3
1        2
5        4
7        8
6        7

我想将其从递归结构转换为 table,其中 child 列在一列中,其最终 parent(parent在所有回收完成后仍然存在)列在另一个中。例如,上面的 table 将导致:

child    ultimate_parent
-----    ---------------
3        4
2        4
1        4
5        4
7        8
6        8

我知道这应该可以使用 SQLites 递归 CTE,但我在开发查询时遇到了问题。以下是我到目前为止的内容,但显然不完整。

WITH RECURSIVE rel(child, parent) AS (
        SELECT child, parent FROM relationships
        UNION ALL
        SELECT child, parent FROM rel
    )
    SELECT * FROM rel;

如有任何帮助,我们将不胜感激。

上述示例table的转储

PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE `relationships` (
    `child` INTEGER,
    `parent`    INTEGER
);
INSERT INTO relationships VALUES(3,4);
INSERT INTO relationships VALUES(2,3);
INSERT INTO relationships VALUES(1,2);
INSERT INTO relationships VALUES(5,4);
INSERT INTO relationships VALUES(7,8);
INSERT INTO relationships VALUES(6,7);
COMMIT;

递归步骤必须使用上一步的数据和原始table来计算下一步的数据:

WITH RECURSIVE ...
    ...
    UNION ALL
    SELECT rel.child,
           relationships.parent
    FROM relationships
    JOIN rel ON rel.parent = relationships.child
)

并且 CTE 生成所有可能的直接和间接 parents;你必须过滤掉最终的 parents,即那些 parents 不是 children:

WITH ...
SELECT *
FROM rel
WHERE parent NOT IN (SELECT child
                     FROM relationships);