Search code examples
sqlvb.netloopsgraphcommon-table-expression

Retrieve cyclic graph data without infinite loop and repeated


I need to query these records to get unique related items:

insert into items(child, parent) 
values (1, 2), (2, 3), (3, 5), (3, 4),
       (4, 5), (6, 7), (1, 8), (8, 1)

I need to pass the input e.g. 1 and get result of related items

 2 3 4 5 8

I tried with SQL / CTE but I failed.

So, I need any solution with VB.NET or SQL help, with big data considered ..

============ Add Query

 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);

Output

2 8 3 5 4 5

Solution

  • I Solved the problem with VB.NET because I need to check repeated items, as follow:

    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