Io utilizzo anche il DB sistemato in modo gerarchico, ossia: ogni record ha un suo id e l'id del padre. Poi utilizzo una funzione ricorsiva per caricare padri e figli.

codice:
Private Function Carica_Tree(Espandi As Boolean, ID_Father As Long, StrFather As String)
    Dim RS_1 As New ADODB.Recordset
    
    Screen.MousePointer = 11
    If ID_Father <> 0 Then
        Sql = "SELECT TABELLA.ID,"
        Sql = Sql & " TABELLA.ID_Padre,"
        Sql = Sql & " TABELLA.Descrizione,"
        Sql = Sql & " TABELLA_Figli.ID_Padre AS Father_Figlio"
        Sql = Sql & " FROM TABELLA LEFT JOIN "
        Sql = Sql & " TABELLA AS TABELLA_FIGLI ON TABELLA.ID ="
        Sql = Sql & " TABELLA_Figli.ID_Padre"
        Sql = Sql & " WHERE TABELLA.ID_Padre =" & ID_Father
        Sql = Sql & " GROUP BY TABELLA.ID, TABELLA.ID_Padre,"
        Sql = Sql & " TABELLA.Descrizione, TABELLA_Figli.ID_Padre"
        ContaQuery = ContaQuery + 1
    Else
        IndiceCar = 0
        Sql = "SELECT * FROM TABELLA"
        Sql = Sql & " WHERE ID_Father =0"
        ContaQuery = ContaQuery + 1
    End If
    Sql = Sql & " ORDER BY TABELLA.Descrizione"
    Cont = 0
    If ID_Father = 0 Then
        On Error Resume Next
        Rs.CacheSize = 150
        On Error GoTo 0
        Rs.Open Sql, Application.Databases.Selected.Connection, adOpenForwardOnly
        'LIVELLO 1
        If Rs.EOF = False Then
            Do While Rs.EOF = False
                Set NodX = Tree.Nodes.Add(, , StrFather & Rs!ID, Rs!Descrizione)
                ContaP = ContaP + 1
	    'Richiamo la stessa funzione
                Carica_Tree Espandi, Rs!ID, StrFather
                StrFather = "Fat"
                Rs.MoveNext
            Loop
        End If
        For Cont = 1 To Tree.Nodes.Count - 1
            Tree.Nodes(Cont).Expanded = Espandi
        Next
        If IndiceCar > 0 Then
	If Tree.Nodes.Item(IndiceCar).Parent Is Nothing Then
	   Tree.Nodes.Item(IndiceCar).Root.Selected = True
	   Tree.Nodes.Item(IndiceCar).Root.Expanded = True
	   Set Tree.DropHighlight = Tree.Nodes.Item(IndiceCar).Root
	Else
	   Tree.Nodes.Item(IndiceCar).Parent.Selected = True
	   Tree.Nodes.Item(IndiceCar).Parent.Expanded = True
	   Set Tree.DropHighlight = Tree.Nodes.Item(IndiceCar).Parent
	End If
        End If
        Set Rs = Nothing
    Else
        'LIVELLI 2 ==> N
        If StrFather = "Fat" Then
            Conta = 1
        Else
            Conta = 0
        End If
        On Error Resume Next
        RS_1.CacheSize = 150
        On Error GoTo 0
        RS_1.Open Sql, Application.Databases.Selected.Connection, adOpenForwardOnly
        If RS_1.EOF = False Then
            Do While RS_1.EOF = False
                If Conta = 1 Then
                    Set NodX = Tree.Nodes.Add("Fat" & ID_Father, tvwChild, _
                    "Son" & RS_1!ID, RS_1!Descrizione)
                Else
                    Set NodX = Tree.Nodes.Add(StrFather & ID_Father, tvwChild, _
                    "Son" & RS_1!ID, RS_1!Descrizione)
                End If
                If RS_1!ID = ID_Touch Then
                    If IndiceCar = 0 Then
                        IndiceCar = NodX.Index
                    End If
                End If
                ContaP = ContaP + 1
                StrFather = "Son"
                If IsNull(RS_1!Father_Figlio) = False Then
                    Carica_Tree Espandi, RS_1!ID, StrFather
                End If
                RS_1.MoveNext
            Loop
        End If
        Set RS_1 = Nothing
    End If
End Function
Spero si capisca, sono in ufficio e non ho molto tempo...