提问人:lady 提问时间:11/12/2023 最后编辑:lady 更新时间:11/14/2023 访问量:81
检索循环图数据,无需无限循环和重复
Retrieve cyclic graph data without infinite loop and repeated
问:
我需要查询这些记录以获取唯一的相关项目:
insert into items(child, parent)
values (1, 2), (2, 3), (3, 5), (3, 4),
(4, 5), (6, 7), (1, 8), (8, 1)
我需要传递输入,例如 1 并获取相关项目的结果
2 3 4 5 8
我尝试过 SQL / CTE,但我失败了。
因此,我需要任何带有 VB.NET 或SQL帮助的解决方案,并考虑大数据。
============ 添加查询
WITH Alter_RC AS (
SELECT sa1.child,
sa1.parent,
CAST(concat(LOWER( sa1.child), ',', LOWER( sa1.parent)) as nvarchar(MAX)) as relpath
FROM items sa1
WHERE LOWER( sa1.child ) = LOWER( '1' )
UNION ALL
SELECT sa1.child,
sa1.parent,
CAST( concat(sa2.relpath, ',', sa1.parent) as nvarchar(MAX)) as relpath
FROM Alter_RC as sa2 inner join items as sa1 on sa2.parent = sa1.child
where LOWER( sa1.parent ) NOT IN (SELECT value FROM STRING_SPLIT(relpath, ','))
)
SELECT parent FROM Alter_RC
OPTION (MAXRECURSION 0);
输出
2 8 3 5 4 5
答:
0赞
Saikat
11/13/2023
#1
下面是在 SQL Server 中使用递归 CTE 的解决方案。请试一试。我不确定它的效果如何。但它肯定会给你你正在寻找的答案。
with main_cte as
(
select distinct
case when parent > child then child
else parent end as child ,
case when parent < child then child
else parent end as parent
from items
) ,
cte as
(
select child , parent from main_cte as a
union all
select a.child , b.parent from cte as a inner join main_cte as b on a.parent = b.child
),
base_cte as
(
select parent as child , child as parent from main_cte as a
),
next_cte as
(
select child , parent from base_cte as a
union all
select b.child , a.parent from next_cte as a inner join base_cte as b on a.child = b.parent
union all
select b.child , a.child from next_cte as a inner join base_cte as b on a.parent = b.parent
) ,
final_cte as
(
select child as person , parent as relatives from
(
select child , parent from cte
union all
select child , parent from next_cte
where child <> parent
) as a
group by child , parent
)
select person , string_agg(cast(relatives as varchar(1)) , ',') as realtives from final_cte group by person;
评论
0赞
lady
11/13/2023
执行不会停止!,我在哪里可以添加:where child = LOWER( '1' ) ?
0赞
lady
11/13/2023
适用于此检查: CREATE TABLE ##test ( 子 nvarchar(50), parent nvarchar(50) ) 插入 ##test ( 子项, 父项) 值 (1, 2), (2, 3), (3, 5), (3, 4), (4, 5), (6, 7), (1, 8), (8, 1) ---- 对于特定项目
0赞
Saikat
11/13/2023
所以你需要特定输入的输出吗?其中 child = 1?这是可能的,但我不明白的是最后的记录。如果 1 的父级是 8,那么反过来怎么可能呢?- 请解释。因此,如果您删除最后一条记录,那么您可以获得所需的输出。如果我在任何地方错了,请告诉我。
0赞
lady
11/13/2023
这些记录中的主要问题是,由于多种方式的循环结果......特别是如果同一个父母在两个不同的兄弟姐妹中......实际上,真实数据更复杂
1赞
Saikat
11/14/2023
好的,明白了。这有效吗?因为我没有看到你有什么数据。我只是尝试在您提供的数据集上执行此操作。
0赞
lady
11/14/2023
#2
我解决了 VB.NET 的问题,因为我需要检查重复的项目,如下所示:
Dim relateditems As New List(Of String)
Private Sub RetreiveItems(item As String)
Dim watch As Stopwatch = Stopwatch.StartNew()
relateditems.Add(item)
Dim Where = " LOWER( sa1.child ) = LOWER('" & item & "' ) "
RecursivelyRetreiveItems(Where)
watch.Stop()
Console.WriteLine(relateditems.Count & " " & watch.Elapsed.TotalMilliseconds)
End Sub
Private Sub RecursivelyRetreiveItems(Where As String)
Dim dt = selectSQLData("SELECT sa1.child as currentItem, sa1.parent as parentItem FROM items sa1 WHERE " & Where & " and fitem_Different_yn = '0' ").Tables(0)
For i = 0 To dt.Rows.Count - 1
If relateditems.Contains(dt.Rows(i)("parentItem").ToString) = False Then
relateditems.Add(dt.Rows(i)("parentItem"))
End If
Next
If dt.Rows.Count > 0 Then
Dim newWhere = "("
For i = 0 To dt.Rows.Count - 1
If newWhere <> "(" Then
newWhere += " OR "
End If
newWhere += "LOWER(sa1.child) = LOWER('" & dt.Rows(i)("parentItem") & "' ) "
Next
newWhere += ") and (" & ("'" + String.Join(",", relateditems) + "'") & " not LIKE concat('%', sa1.parent, '%') ) "
RecursivelyRetreiveItems(newWhere)
End If
End Sub
评论