【发布时间】:2018-01-04 22:11:47
【问题描述】:
我有一棵树,树中的特定节点可以出现在树中的另一个节点中。 (在我的示例中为 2):
1
/ \
2 3
/ \ \
4 5 6
\
2
/ \
4 5
通知 2 重复。 1岁以下第一名,6岁以下第二名。 我的递归是:
with cte (ParentId, ChildId, Field1, Field2) AS (
select BOM.ParentId, BOM.ChildId, BOM.Field1, BOM.Field2
from BillOfMaterials BOM
WHERE ParentId=x
UNION ALL
SELECT BOM.ParentId, BOM.ChildId, BOM.Field1, BOM.Field2 FROM BillOfMaterials BOM
JOIN cte on BOM.ParentId = cte.ChildId
)
select * from cte;
但问题是结果关系 2-4 和 2-5 重复(第一个来自关系 1-2,第二个来自关系 6-2):
ParentId ChildId OtherFields
1 2
1 3
2 4 /*from 1-2*/
2 5 /*from 1-2*/
3 6
6 2
2 4 /*from 6-2*/
2 5 /*from 6-2*/
有什么办法可以跳过重复的关系吗?我看不出任何逻辑为什么递归应该在已经存在的行上运行。它会更快。类似的东西:
with cte (ParentId, ChildId, Field1, Field2) AS (
select BOM.ParentId, BOM.ChildId, BOM.Field1, BOM.Field2
from BillOfMaterials BOM
WHERE ParentId=x
UNION ALL
SELECT BOM.ParentId, BOM.ChildId, BOM.Field1, BOM.Field2 FROM BillOfMaterials BOM
JOIN cte on BOM.ParentId = cte.ChildId
------> WHERE (select count(*) FROM SoFarCollectedResult WHERE ParentId=BOM.ParentId AND ChildId=BOM.ChildId ) = 0
)
select * from cte;
我找到了this thread,但它已经 8 岁了。
我正在使用 SQL Server 2016。
如果这是不可能的,那么我的问题是如何从最终结果中删除重复项,但仅在 ParentId 和 ChildId 列上检查不同?
已编辑:
预期结果是:
ParentId ChildId OtherFields
1 2
1 3
2 4
2 5
3 6
6 2
【问题讨论】:
-
你如何区分 1 的 2 个孩子和 6 的 2 个孩子?
-
您的数据有缺陷。你根本不能把它像那样放在一起。你怎么知道一组 2,4 属于 1 之下,而另一组属于 6 之下。如果你需要那种关系,你需要重建你的数据结构,因为作为一个标准的父子它是行不通的。
-
这里有一个根本问题。可以根据不同的方法遍历树。没有真正意义上的“第一”——谁是说哪个节点的出现值得孩子。节点不能“实例化”然后通过它们的祖先来区分,这使得它们不再是节点。
-
我的数据肯定没问题。在表中,我有记录 1(父)2(子)1(位置)和 6(父)2(子)2(位置)。所有这三个字段在树中都有唯一的位置。但是我没有理由为节点 2 递归地获取所有(可能是 10 级或更多)两次(大写)。
标签: sql-server sql-server-2016