Damit rekursive CTE Besuch Knoten mehrfach

Betrachten Sie die folgenden einfachen DAG:

  1->2->3->4

Sowie eine Tabelle, #bar, beschreiben (ich bin die mit SQL Server 2005):

parent_id   child_id
1           2
2           3
3           4
//... other edges, not connected to the subgraph above

Jetzt Stell dir vor, ich habe einige andere willkürliche Kriterien, wählen Sie den ersten und den letzten Kanten, d.h. 1->2-und 3->4. Ich möchte, um diese zu finden, den rest meines graph.

Kann ich schreiben Sie eine rekursive CTE wie folgt (ich verwende die Terminologie von MSDN):

with foo(parent_id,child_id) as (
// anchor member that happens to select first and last edges:
select parent_id,child_id from #bar where parent_id in (1,3)
union all
// recursive member:
select #bar.* from #bar
join foo on #bar.parent_id = foo.child_id
)
select parent_id,child_id from foo

Jedoch, diese Ergebnisse in Rand-3->4 als zweimal gewählt:

parent_id  child_id
1          2
3          4
2          3
3          4    // 2nd appearance!

Wie kann ich verhindern, dass die Abfrage von recursing in Teilgraphen, die bereits beschrieben worden? Könnte ich erreichen, wenn, in meinem "Rekursives Element" - Teil der Abfrage, könnte ich die Referenz alle Daten, die abgerufen wurde, der vom rekursiven Allgemeinen Tabellenausdruck so weit (und liefern ein Prädikat, das angibt, in das rekursive Element ohne Knoten bereits besucht). Ich denke aber, ich kann auf Daten zugreifen, die zurückgegeben wurde der letzten iteration des rekursiven Elements nur.

Das wird nicht gut skalieren, wenn es eine Menge solcher Wiederholung. Gibt es eine Möglichkeit, dies zu verhindern unnötige zusätzliche Rekursion?

Beachten Sie, dass ich verwenden könnte, "select distinct" in der letzten Zeile meiner Anweisung, um die gewünschten Ergebnisse zu erreichen, aber dies scheint angewandt werden nach alle die (wiederholt) die Rekursion erfolgt, so dass ich nicht denke, dass das eine ideale Lösung.

Bearbeiten - hainstech schlägt vor, stoppen die Rekursion durch ein Prädikat hinzufügen ausschließen recursing Wege beschritten wurden, die explizit in den ersten Satz, D. H. recurse nur where foo.child_id not in (1,3). Das funktioniert für den oben genannten Fall nur, weil Sie es sich einfach - alle wiederholten Abschnitten, beginnen die Anker Menge von Knoten. Löst es nicht den Allgemeinen Fall, wo Sie vielleicht nicht. beispielsweise, betrachten Sie das hinzufügen von Kanten 1->4 und 4->5 zu den oben genannten Satz. Edge-4->5 erfasst werden, um die zweimal, einmal mit den vorgeschlagenen Prädikat. 🙁

InformationsquelleAutor der Frage bacar | 2009-05-06

Schreibe einen Kommentar