Ich habe eine Kanten Tabelle in meiner PostgreSQL-Datenbank, die die Kanten eines gerichtet Graph, mit zwei Säulen steht: node_from und node_to (Wert ist die ID eines Knotens).PostgreSQL SQL-Abfrage für eine ganze ungerichteten Graphen durchlaufen und alle Kanten Rückkehr gefunden
einen einzelnen Knoten (initial_node) Da ich die gesamte Grafik zu durchqueren können, möchte aber in eine ungerichtete Weise.
Was ich meine ist, zum Beispiel für die folgende Grafik:
(a->b)
(c->b)
(c->d)
Wenn initial_node ist ein, b, c oder d, auf jeden Fall, ich [a, b, c, d].
ich verwendet, um die folgende SQL-Abfrage (basierend auf http://www.postgresql.org/docs/8.4/static/queries-with.html):
WITH RECURSIVE search_graph(uniq, depth, path, cycle) AS (
SELECT
CASE WHEN g.node_from = 'initial_node' THEN g.node_to ELSE g.node_from END,
1,
CASE WHEN g.node_from = 'initial_node' THEN ARRAY[g.node_from] ELSE ARRAY[g.node_to] END,
false
FROM edges g
WHERE 'initial_node' in (node_from, node_to)
UNION ALL
SELECT
CASE WHEN g.node_from = sg.uniq THEN g.node_to ELSE g.node_from END,
sg.depth + 1,
CASE WHEN g.node_from = sg.uniq THEN path || g.node_from ELSE path || g.node_to END,
g.node_to = ANY(path) OR g.node_from = ANY(path)
FROM edges g, search_graph sg
WHERE sg.uniq IN (g.node_from, g.node_to) AND NOT cycle
)
SELECT * FROM search_graph
Es funktionierte gut ... Bis ich einen Fall mit 12 Knoten hatte, die alle zusammen in alle Richtungen verbunden sind (für jedes Paar Ich habe beide (a-> b) und (b-> a)), was die Abfrage unendlich lange macht. (Wenn UNION ALL in UNION geändert wird, wird die Schleife nicht gelöscht.)
Hat jemand einen Ratschlag, um dieses Problem zu lösen?
Prost,
Antoine.
Vielen Dank Ziggy! Die Abfrage wird für die komplexesten Fälle nicht endlos wiederholt, und selbst für einfache Diagramme ist sie doppelt so schnell wie meine vorherige Implementierung. –
Nur um etwas hinzuzufügen, in meinem Fall für den ersten Teil ist es: SELECT DISTINCT "zu" AS "uniq" FROM Kanten WHERE "von" = 'initial_node' UNION SELECT DISTINCT "bis" AS "uniq" FROM Kanten WO " zu "= 'initial_node') –