通过递归CTE找到最终父母

时间:2017-10-14 16:34:45

标签: sqlite common-table-expression recursive-query

我有一个包含子ID及其父ID的SQLite表。给定父级也可能出现在子列中。例如:

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

我想将它从递归结构转换为一个表,其中子列在一列中,并且其最终父级(在完成所有重用之后保留的父级)列在另一列中。例如,上表将导致:

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;

非常感谢任何帮助。

上面示例表的转储

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;

1 个答案:

答案 0 :(得分:1)

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

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

CTE产生所有可能的直接和间接父母;你必须过滤掉最终的父母,即那些不是孩子的父母:

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