Nts*_*alt 5 sql directed-acyclic-graphs transitive-closure-table
我有以下 DAG
A --> B
| |
v v
C --> D
Run Code Online (Sandbox Code Playgroud)
这是关闭表
| Ancestor | Descendant | Depth |
---------------------------------
| A | A | 0 |
| A | B | 1 |
| A | C | 1 |
| A | D | 2 |
| A | D | 2 |
| B | B | 0 |
| B | D | 1 |
| C | C | 0 |
| C | D | 1 |
| D | D | 0 |
Run Code Online (Sandbox Code Playgroud)
我将如何删除路径B > D(从而删除A > B > D)而不删除A > C > D和C > D。
现在我正在使用以下查询,但它仅在每个节点只有 1 个父节点时才有效。
DELETE FROM `Closure`
WHERE `Descendant` IN (SELECT `Descendant` FROM `Closure` WHERE `Ancestor`=@Node)
AND `Ancestor` NOT IN (SELECT `Descendant` FROM `Closure` WHERE `Ancestor`=@Node);
Run Code Online (Sandbox Code Playgroud)
用自然语言来说,这将是:“如果除了 B 之外 D 没有父辈也是 A 的后代,则删除与 D 的祖先-后代关系”。那是对的吗?
(编辑:不,这是不正确的;不仅必须删除与 D 的关系,而且还必须删除与D 的每个后代的关系。因此,该标准无效......)
我的暂定 SQL 是:
DELETE a
FROM Closure AS a
INNER JOIN Closure AS b ON a.Descendant = b.Descendant
WHERE
a.Descendant IN (SELECT Descendant FROM Closure WHERE Ancestor = {Child}) AND
b.Depth = 1 AND
b.Ancestor != {Parent} AND
a.Ancestor NOT IN (SELECT Ancestor FROM Closure WHERE Descendant = b.Ancestor)
Run Code Online (Sandbox Code Playgroud)
(抱歉,如果我的查询错误 - 或者使用了非标准功能 - 我实际上对此没有经验。但是我的自然语言描述应该能够洞察查询中实际需要的内容)
更新:再想一想,我不相信我的查询适用于所有情况。考虑一下:
A --> B --> D --> E --> F
Run Code Online (Sandbox Code Playgroud)
因此,A >> F即使应该删除,也不会被删除。抱歉,我无能为力,但这似乎是一个太大的问题,无法用单个查询来解决。我建议首先寻找算法解决方案,然后看看如何在您的案例中实现它。