在多个父级的封闭表中移动

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 > DC > 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)

mgi*_*nbr 1

用自然语言来说,这将是:“如果除了 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)
  1. F 是 D 的后代(正确)
  2. E 是 F 的父级(正确)
  3. E 不是 B(正确)
  4. A 不是 E 的祖先(错误)

因此,A >> F即使应该删除,也不会被删除。抱歉,我无能为力,但这似乎是一个太大的问题,无法用单个查询来解决。我建议首先寻找算法解决方案,然后看看如何在您的案例中实现它。