PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

PostgreSQL übergibt Daten vom rekursiven CTE an die Funktion

Sie können die Pfadsuche effizienter gestalten, wenn Sie ganz unten beginnen. Beginnen Sie bei den Kindern. Wenn Sie beim übergeordneten Element beginnen, müssen alle untergeordneten Elemente durchlaufen werden. wohingegen, wenn Sie vom Kind aus suchen, es nur einen Elternteil hat, daher wird keine Zeit damit verschwendet, den Pfad zwischen Quelle und Ziel zu finden.

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

Ausgabe:

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

Live-Test:http://www.sqlfiddle.com/#!1/13e6b/1

Ähnlich wie hier:Wie man in SQL SERVER 2005 dem Elternteil ein Kind gibt

Dies ist optimiert, schneide die Rekursion zum übergeordneten Element ab, wenn es das spezifische bereits findet (Quelle).

Quelle =2

Ziel =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

Ausgabe:

SOURCE   TARGET  PATH
2        4       2.4
4        9       2.4.9

Live-Test:http://www.sqlfiddle.com/#!1/13e6b/16