Je dispose d'un bords table de ma base de données PostgreSQL qui représente les arêtes d'un graphe dirigé, avec deux colonnes: node_from et node_to (la valeur est l'identifiant d'un noeud).PostgreSQL requête SQL pour parcourir tout un graphe non orienté et retourner tous les bords trouvé
un seul noeud Étant donné (initial_node) Je voudrais pouvoir traverser le graphe entier, mais d'une manière undirected.
Ce que je veux dire est, par exemple pour le graphique suivant:
(a->b)
(c->b)
(c->d)
Si initial_node est un dans tous les cas, b, c ou d, je obtiendrait [un, b, c, d].
J'ai utilisé la requête SQL suivante (basée sur 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
Il a bien fonctionné ... Jusqu'à ce que j'ai eu un cas avec 12 noeuds qui sont tous reliés entre eux, dans toutes les directions (pour chaque paire J'ai les deux (a-> b) et (b-> a)), ce qui rend les boucles de requête indéfiniment. (La modification de UNION ALL en UNION n'élimine pas la boucle.)
Quelqu'un a-t-il des conseils pour résoudre ce problème?
Cheers,
Antoine.
Merci beaucoup Ziggy! La requête ne boucle pas indéfiniment pour les cas les plus complexes et même pour les graphes simples, elle est deux fois plus rapide que mon implémentation précédente. –
Juste pour ajouter quelque chose, dans mon cas pour la partie initiale, c'est: SELECT DISTINCT "à" AS "uniq" FROM bords WHERE "de" = 'initial_node' UNION SELECT DISTINCT "à" AS "uniq" FROM bords OERE " à "= 'initial_node') –