输入表:区域
+---------------+---------------+---------- +-----------+
| Child | Parent | Level | levelname|
+---------------+---------------+---------- +-----------+
| All Region | All Region | 1 | national |
| Africa Region | All Region | 2 | region |
| America | All Region | 2 | region |
| Asia | All Region | 2 | region |
| Europe Region | All Region | 2 | region |
| Africa | Africa Region | 3 | Subregion |
| Asia Pacific | Asia | 3 | Subregion |
| Europe | Europe Region | 3 | Subregion |
| North America | America | 3 | Subregion |
| South America | America | 3 | Subregion |
| Argentina | South America | 4 | Country |
| Australia | Asia Pacific | 4 | Country |
| Pakistan | Asia Pacific | 4 | Country |
| South Africa | Africa | 4 | Country |
| Tunisia | Africa | 4 | Country |
| Uruguay | South America | 4 | Country |
+-------------------------------------------------------+
此处,区域为4级
国家
他们拥有0,1,2和3个祖先,例如一个国家有子区域,地区和所有地区作为祖先,假设我们给予"乌拉圭" ,然后输出将是南美洲,美国,所有地区。现在,我需要对此表进行查询,该查询将检索给定"孩子的所有祖先"
答案 0 :(得分:4)
你最好的选择是递归CTE:
With recRegions AS
(
/*Recursive Seed*/
SELECT
Child,
Parent,
Level,
0 as Depth,
CAST(Child as VARCHAR(5000)) as Path
FROM
Regions
WHERE
Child=<WhateverChildYouAreWanting>
UNION ALL
/*Recursive Term*/
SELECT
Regions.Child,
Regions.Parent,
Region.Level,
recRegions.Depth + 1,
recRegions.Path || '>' || Region.Child
FROM
recRegions
INNER JOIN Regions on
recRegions.parent = Regions.Child
Where recRegions.Depth < 10
)
Select Parent as Ancestors FROM recRegions;
递归查询最初可能有点棘手,但是如果你分解它,那就有意义了:
recRegions
连接到您的Region
表,将子连接到父级。数据库将触及此递归术语,直到没有更多记录返回,这意味着我们已经一直爬上你的层次结构。Parent
字段记录。通常当你看到一个布局为child | parent | attributes | of | that | relationship
的桌子时,你可以转向超强大的递归CTE来快速理解它。
正如@dnoeth在你的Q评论中提到的,你也可以将Regions表连接到自己4次,因为你的层次结构似乎只有4个深度。递归查询并不关心深度,因此如果您为层次结构添加更多深度,则不必编辑SQL来拉动祖先。
更新以添加&#34;深度&#34;字段跟踪递归并在10之后停止。还添加了一个&#34;路径&#34;字段,用于跟踪从子级构建的层次结构。如果您的层次结构循环存在问题(向子级报告的子级报告给子级导致无限循环),则可以使用以下SQL语句而不是上面的SELECT parent FROM
版本:
SELECT * FROM recRegions;
现在,您将看到层次结构中每个节点的路径和深度,以便您可以修复数据,或者递归CTE以避免循环。