SQL или PL / pgSQL-запрос PostgreSQL для обхода ориентированного графа и возврата всех найденных ребер - PullRequest
3 голосов
/ 09 августа 2010

Я не особенно привык генерировать сложные запросы SQL, и мне трудно смешивать мое понимание процедурных языков и операций на основе множеств в разработка рекурсивного запроса для обхода сети. Я хотел бы найти набор ребер, которые лежат «в восходящем направлении» конкретного узла, путем проведения сначала поиска по глубине ориентированного графа (каждый узел может иметь более одного ребра в восходящем направлении) и в идеале хотел бы реализовать это в SQL.

Псевдокод того, что я хочу сделать, выглядит следующим образом:

interesting_pipes = Pipes[]

func find_all_pipes_upstream(node n)
 if is_inlet(nodename)
    return Nil
 else
   for p in upstream_pipes:
     if p in interesting_pipes:
       return Nil
   else
     interesting_pipes.append(p)
     find_all_pipes_upstream(upstream_node(p))

Я уже написал следующие функции на чистом SQL:

upstream_pipes(node_name varchar) RETURNS SETOF "Pipes"
upstream_node(pipe_name varchar) RETURNS "Node"
is_inlet(node_name) RETURNS boolean

но я пытаюсь понять, как управлять областями видимости и типами возврата при преобразовании указанного псевдокода в запрос PostgreSQL WITH RECURSIVE или функцию PL / pgSQL. Большинство примеров, которые я видел для WITH RECURSIVE запросов, были разработаны для обхода деревьев, где у каждого узла есть только один родительский элемент. Кто-нибудь есть какие-либо советы / советы, как лучше всего по этому поводу?

Приветствия

Будет

1 Ответ

3 голосов
/ 11 августа 2010

См .:

http://www.postgresql.org/docs/8.4/static/queries-with.html

Этот запрос будет зациклен, если связи ссылок содержат циклы.Поскольку нам требуется вывод "глубины", просто изменение UNION ALL на UNION не устранит зацикливание.Вместо этого нам нужно определить, достигли ли мы того же ряда снова, следуя определенному пути ссылок.Мы добавляем два столбца: путь и цикл к склонному к петле запросу:

...