我在数据库中有下表:
+-------------+ +-------------+-------------+ +---------------------------+
| project1 | | project2 + | project3 |
+-------------+ +-------------+-------------+ +---------------------------+
| project1_id | | project2_id | project1_id | | project3_id | project2_id |
+-------------+ +-------------+-------------+ +---------------------------+
| hnc1 | | hnc4 | hnc1 | | hnc7 | hnc4 |
| hnc2 | | hnc5 | hnc1 | | hnc8 | hnc4 |
| hnc3 | | hnc6 | hnc3 | | hnc9 | hnc6 |
+-------------+ +-------------+-------------+ +---------------------------+
我需要从所有三个表中检索给定 ID 的所有后代 - 如果在任何表中找到 ID 本身,也包括在内。
例如,如果我使用 ID “hnc4”进行查询,它应该得到:
+-------------+
| descendants |
+-------------+
| hnc7 |
| hnc8 |
| hnc4 |
+-------------+
如果我使用 ID 'hnc1'进行查询:
+-------------+
| descendants |
+-------------+
| hnc4 |
| hnc5 |
| hnc7 |
| hnc8 |
| hnc1 |
+-------------+
即使 ID 仅在最后一个表中,查询也必须有效project3
。
我正在搜索并发现递归 CTE 可能很有用,但我不知道如何使用 3 个表来实现它。
关于如何获得正确结果的任何指导?
标识符不能参数化,所以我想不出用 rCTE遍历多个表的方法。
对每个表进行假设
UNIQUE
或PRIMARY KEY
约束,因此我们不必担心重复。我将查询包装在 SQL 函数中以简化 ID 的传递:
SELECT
onproject2
进入 CTEp2
,因此我们可以重用SELECT
on的结果project3
。project1
和不需要同样的project3
。称呼:
准确地产生您想要的结果。
SQL小提琴。
如果表很大,一定要有正确的索引。有关的:
模式升级
您不需要三个表来进行单一继承。您可以使用一张表来做到这一点。这不仅更快、更干净,而且在保持完整性方面更好,而且它允许超过三个级别的深度(n 级)
现在我们可以查询它,
这种模式称为“单表层次结构”或自引用表。
向后兼容
事实上,如果你想回到愚蠢的三表设计......
创建一个执行最后一个查询的视图,
继续关注那个..
您的查询
要获取我表中的所有祖先
hcn4
,4
请更改终点并在相反方向构建它。想要
hcn1
只需要将其切换为WHERE id = 1
;等价的,
f_all_descendants_of(int)
变成,