PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

PostgreSQL transmet les données du CTE récursif à la fonction

Vous pouvez rendre la recherche du chemin plus efficace si vous commencez par le bas. Commencez par les enfants. Si vous commencez par le parent, cela implique de parcourir tous les enfants; alors que si vous avez cherché à partir de l'enfant, il n'a qu'un seul parent, vous ne perdrez donc pas de temps à trouver le chemin entre la source et la cible.

with recursive find_parent(source, target, recentness) as
(
    select source, target, 0 
    from tbl
    where target = 9

    union all

    select i.source, i.target, fp.recentness + 1
    from tbl i
    join find_parent fp on i.target = fp.source
),
construct_path(source, target, recentness, path) as
(
  select source, target, recentness, source || '.' || target
  from find_parent 
  where recentness = (select max(recentness) from find_parent)

  union

  select dd.source, dd.target, dd.recentness, cp.path || '.' || dd.target
  from find_parent dd
  join construct_path cp on dd.recentness = cp.recentness - 1  
)
select source, target, path 
from construct_path
order by recentness desc

Sortie :

SOURCE   TARGET   PATH
1        2        1.2
2        4        1.2.4
4        9        1.2.4.9

Test en direct :http://www.sqlfiddle.com/#!1/13e6b/1

Similaire à ceci :Comment obtenir le parent donné à un enfant dans SQL SERVER 2005

Ceci est optimisé, coupez la récursivité au parent s'il trouve déjà la source spécifique.

Provenance =2

Cible =9

with recursive find_parent(source, target, recentness) as
(
    select source, target, 0 
    from tbl
    where target = 9

    union all

    select i.source, i.target, fp.recentness + 1
    from tbl i
    join find_parent fp on i.target = fp.source 
         -- despite the name, this target is another one's source
         and i.target <> 2
)
,construct_path(source, target, recentness, path) as
(
    select source, target, recentness, source || '.' || target
    from find_parent 
    where recentness = (select max(recentness) from find_parent)

    union

    select dd.source, dd.target, dd.recentness, cp.path || '.' || dd.target
    from find_parent dd
    join construct_path cp on dd.recentness = cp.recentness - 1  

)
select source, target, path
from construct_path
order by recentness desc

Sortie :

SOURCE   TARGET  PATH
2        4       2.4
4        9       2.4.9

Test en direct :http://www.sqlfiddle.com/#!1/13e6b/16