SQL 查询 Parent-Child-Grandchild 关系
SQL Query for Parent-Child-Grandchild relationship
我想问一下任何 SQL 查询都可以与级别建立 parent-child-grandchild 关系。另外,我希望 child 关注他们的 parent。
我的table是这样的
ID |ParentID| ChildID |Type
0048 |50199956|50856732(MB) |Got Child
0049 |50199956|50856711(GA) |Got Child
0050 |50199956|YUIOP-78-OP |No Child
ID |ParentID | ChildID |Type
0051|50856732(MB)|NUYU-IO-OO |Got Child
0052|50856732(MB)|5085675939 |No Child
0053|50856732(MB)|YRTOP-VG-34 |No Child
ID |ParentID | ChildID |Type
0122|NUYU-IO-OO|55466789 |No Child
0123|NUYU-IO-OO|34561277 |No Child
0124|NUYU-IO-OO|46796439 |No Child
ID |ParentID | ChildID |Type
0067 |50856711(GA)|IOP78I-UI-67 |No Child
我想要的结果:
ID |ParentID |ChildID |Type
0048 |50199956 |50856732(MB) |Got Child
0049 |50856732(MB)|NUYU-IO-OO |Got Child
0122 |NUYU-IO-OO |55466789 |No Child
0123 |NUYU-IO-OO |34561277 |No Child
0124 |NUYU-IO-OO |46796439 |No Child
0050 |50856732(MB)|5085675939 |No Child
0051 |50856732(MB)|YRTOP-VG-34 |No Child
0067 |50199956 |50856711(GA) |Got Child
0052 |50856711(GA)|IOP78I-UI-67 |No Child
0053 |50199956 |YUIOP-78-OP |No Child
已编辑
已解决。只需使用 CTE 递归并在 child 部分添加 ID(varchar50)) 和 ID,然后按 ID 排序。感谢所有帮助我的人^^
我相信这里的诀窍是知道如何按代排序。在这种情况下,对于每一行,您都必须检查它们是顶层、中间层还是底层。
因为只有三代,我们可以偷懒,自己加入两次,创建一个家族ID。 COALESCE
让我们默认为 grandparent 世代的 ID,但如果它不存在(即,这一行 不是 grandchild ),那么它将使用 parent,但是如果 that 不存在(即,这一行不是 child),那么它'将使用它自己的 ID(假设这一行是 grandparent)。通过按此 ID 排序,我们将一行的所有成员分组在一起。然后在该家庭 ID 中,按 ID 字段排序,该字段对于较早的几代人来说似乎较低。
SELECT
a.id
,a.parentID
,a.childID
,COALESCE(c.ID, b.ID, a.ID) as sort_id --if I have grandparents, sort by them, otherwise sort by my parents, otherwise myself
FROM table a
LEFT JOIN table b ON a.parentID = b.childID --find my parents
LEFT JOIN table c ON b.parentID = c.childID --find my grandparents
ORDER BY sort_id, a.id --taking advantage of the fact that earlier generations have lower ID values
使用递归 CTE 按层次结构路径排序
with h as(
-- top level rows, no parent detected
select cast(ChildID+'>' as varchar(max)) as path, *
from MyTable t1
where not exists( select 1 from MyTable t2 where t1.ParentID = t2.ChildID)
--
union all
select path + t.childID + '>', t.*
from h
join MyTable t on h.ChildID = t.ParentID
)
select *
from h
order by path;
我想问一下任何 SQL 查询都可以与级别建立 parent-child-grandchild 关系。另外,我希望 child 关注他们的 parent。
我的table是这样的
ID |ParentID| ChildID |Type
0048 |50199956|50856732(MB) |Got Child
0049 |50199956|50856711(GA) |Got Child
0050 |50199956|YUIOP-78-OP |No Child
ID |ParentID | ChildID |Type
0051|50856732(MB)|NUYU-IO-OO |Got Child
0052|50856732(MB)|5085675939 |No Child
0053|50856732(MB)|YRTOP-VG-34 |No Child
ID |ParentID | ChildID |Type
0122|NUYU-IO-OO|55466789 |No Child
0123|NUYU-IO-OO|34561277 |No Child
0124|NUYU-IO-OO|46796439 |No Child
ID |ParentID | ChildID |Type
0067 |50856711(GA)|IOP78I-UI-67 |No Child
我想要的结果:
ID |ParentID |ChildID |Type
0048 |50199956 |50856732(MB) |Got Child
0049 |50856732(MB)|NUYU-IO-OO |Got Child
0122 |NUYU-IO-OO |55466789 |No Child
0123 |NUYU-IO-OO |34561277 |No Child
0124 |NUYU-IO-OO |46796439 |No Child
0050 |50856732(MB)|5085675939 |No Child
0051 |50856732(MB)|YRTOP-VG-34 |No Child
0067 |50199956 |50856711(GA) |Got Child
0052 |50856711(GA)|IOP78I-UI-67 |No Child
0053 |50199956 |YUIOP-78-OP |No Child
已编辑
已解决。只需使用 CTE 递归并在 child 部分添加 ID(varchar50)) 和 ID,然后按 ID 排序。感谢所有帮助我的人^^
我相信这里的诀窍是知道如何按代排序。在这种情况下,对于每一行,您都必须检查它们是顶层、中间层还是底层。
因为只有三代,我们可以偷懒,自己加入两次,创建一个家族ID。 COALESCE
让我们默认为 grandparent 世代的 ID,但如果它不存在(即,这一行 不是 grandchild ),那么它将使用 parent,但是如果 that 不存在(即,这一行不是 child),那么它'将使用它自己的 ID(假设这一行是 grandparent)。通过按此 ID 排序,我们将一行的所有成员分组在一起。然后在该家庭 ID 中,按 ID 字段排序,该字段对于较早的几代人来说似乎较低。
SELECT
a.id
,a.parentID
,a.childID
,COALESCE(c.ID, b.ID, a.ID) as sort_id --if I have grandparents, sort by them, otherwise sort by my parents, otherwise myself
FROM table a
LEFT JOIN table b ON a.parentID = b.childID --find my parents
LEFT JOIN table c ON b.parentID = c.childID --find my grandparents
ORDER BY sort_id, a.id --taking advantage of the fact that earlier generations have lower ID values
使用递归 CTE 按层次结构路径排序
with h as(
-- top level rows, no parent detected
select cast(ChildID+'>' as varchar(max)) as path, *
from MyTable t1
where not exists( select 1 from MyTable t2 where t1.ParentID = t2.ChildID)
--
union all
select path + t.childID + '>', t.*
from h
join MyTable t on h.ChildID = t.ParentID
)
select *
from h
order by path;