表示为边列表的图形、树、链等通常是递归公用表表达式(即WITH RECURSIVE查询)的良好用途。
就像是:
WITH RECURSIVE walk(id, id_ancestor, id_entry, bool_flag, id_root, generation) AS (
SELECT id, id_ancestor, id_entry, bool_flag, id, 0
FROM RELATIONSHIP_TABLE
WHERE id_ancestor IS NULL
UNION ALL
SELECT x.id, x.id_ancestor, x.id_entry, x.bool_flag, walk.id_root, walk.generation + 1
FROM RELATIONSHIP_TABLE x INNER JOIN walk ON x.id_ancestor = walk.id
)
SELECT
id_entry, id_root, id
FROM (
SELECT
id, id_entry, bool_flag, id_root, generation,
max(CASE WHEN bool_flag THEN generation END ) OVER w as max_enabled_generation
FROM walk
WINDOW w AS (PARTITION BY id_root ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
) x
WHERE generation = max_enabled_generation;
...尽管感觉确实应该有比跟踪我们在每条道路上走了多少代更好的方法来做到这一点。
如果id_entry对树的所有成员都是通用的,则可以避免需要跟踪id_root. 您应该创建一个UNIQUE约束(id_entry, id)和一个外键约束FOREIGN KEY (id_entry, id_ancestor) REFERENCES (id_entry, id)以确保顺序一致,然后使用:
WITH RECURSIVE walk(id, id_ancestor, id_entry, bool_flag, generation) AS (
SELECT id, id_ancestor, id_entry, bool_flag, 0
FROM RELATIONSHIP_TABLE
WHERE id_ancestor IS NULL
UNION ALL
SELECT x.id, x.id_ancestor, x.id_entry, x.bool_flag, walk.generation + 1
FROM RELATIONSHIP_TABLE x INNER JOIN walk ON x.id_ancestor = walk.id
)
SELECT
id_entry, id
FROM (
SELECT
id, id_entry, bool_flag, generation,
max(CASE WHEN bool_flag THEN generation END ) OVER w as max_enabled_generation
FROM walk
WINDOW w AS (PARTITION BY id_entry ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
) x
WHERE generation = max_enabled_generation;
由于这为您提供了与根父母匹配的最终后代表,因此您现在可以使用常规WHERE子句进行过滤,只需 append AND bool_flag。如果您想排除在此过程中任何bool_flag时候设置为 false 的链,您可以添加查询的连接。WHERE bool_valueRECURSIVE
SQLFiddle 示例:http ://sqlfiddle.com/#!12/92a64/3