> On Aug 21, 2019, at 3:35 AM, Francisco Olarte <fola...@peoplecall.com> wrote:
> 
> Pablo:
> 
> On Tue, Aug 20, 2019 at 6:49 PM pabloa98 <pablo...@gmail.com> wrote:
>> Thank you for your responses Rob. Appreciated. The problem with recursive 
>> queries is that they are executed several times and it has and impact in 
>> performance.
>> I need a subset of those rows and I want them in one pass.
>> I discovered that ltree extension could be useful. I will play with it 
>> today. I am sure there's a way to find al the nodes in O(n) time with n = 
>> size of the resulset ...
> 
> Unless you have some extra conditions in a table ( like
> "autoincremented immutable primary key and parents are always created
> before childs" ) I think your problem of "get all the descendant ( i
> do not like to call them children ) nodes of a given id" can not be
> solved in one pass.
> 
> I mean, if you are getting descendants of the node N1, you need to
> read the last node, NL, of the table to know if it is a child of N1.
> But then you have to read the table again to find childs of NL.
> 
> Of course, if you have something like "hierarchical ids" you can
> traverse ordering by it and know NL MUST be childless, and build the
> tree rooted on node N1 as you go, but without some of this conditions
> I do not think it can be done in an "ideal" db ( which lets you scan
> in any order you can define from just a row without cost ) in one scan
> ( storing and prunning the whole tree as you go is cheating ).
> 
> Also, if your node ids come from a serial and are immutables, or you
> take a little care when mutating them, you can do it traversing by id,
> but you need a full scan, a recursive query with several index scans
> may easily be faster in wide trees.
> 
> 
> Francisco Olarte.
If you accept Francisco’s thesis then you may be interested in this
with recursive descendants (last, children) as 
(select c.c, array[null::int] from kids c where not exists (select 1 from kids 
p where c.c = p.p)
 union all
 select k.p, array[k.c] || l.children from kids k, descendants l where k.c = 
l.last)
 select a.last, array_agg(distinct(a.kids))as clan from (select last, 
unnest(array_remove(children, null)) as kids from descendants where children[1] 
is not null) as a group by last order by last
 last |           clan           
------+--------------------------
    1 | {2,3,4,21,22,23,221,222}
    2 | {21,22,23,221,222}
   22 | {221,222}
(3 rows)
No comment on performance other than to say that if you are interested in the 
result for a given seed parent then performance would likely correlate with the 
average depth of your lineages.

I believe the ascending order of the members of each clan is completely 
fortuitous unless it’s a consequence of distinct?



Reply via email to