Thread: WITH RECURSIVE question

WITH RECURSIVE question

From
"Marc Mamin"
Date:
Hello,

WITH RECURSIVE queries are quite new for me, so I'm not sure if
following is possible



CREATE TEMP TABLE forest (node int,parent int);
INSERT INTO  forest VALUES
(1, null),
(2, 1),
(3, 2),
(4, null),
(5, 4),
(6,5);


WITH RECURSIVE struc (pref, id, depth ) AS (
  SELECT '', node, 1 from forest where node= 4
  UNION ALL
  SELECT (case when struc.pref= '' then '\' else struc.pref end )||
'...' ,
         node,
         struc.depth +1
  FROM forest JOIN struc ON parent=struc.id
  )
  SELECT * FROM struc;

 (path,node,depth)
           4  1
  \...     5  2
  \......  6  3

This is fine as long as I start with a given node (here node= 4).

But How can I retrieve the complete structure in one query ?
do I have to use a procedure for that ?

Something like :

WITH FOR_EACH (node) AS ( SELECT node from forest where parent IS NULL)
SELECT * FROM (
  WITH RECURSIVE struc (pref, id, depth ) AS (
    SELECT '', node, 1 from forest where node= FOR_EACH.node
    UNION ALL
    SELECT (case when struc.pref= '' then '\' else struc.pref end )||
'...' ,
           node,
           struc.depth +1
    FROM forest JOIN struc ON parent=struc.id
    )
    SELECT * FROM struc
)one_tree
;

           1  1
  \...     2  2
  \......  3  3
           4  1
  \...     5  2
  \......  6  3


best regards,

Marc Mamin

Re: WITH RECURSIVE question

From
Andreas Kretschmer
Date:
Marc Mamin <M.Mamin@intershop.de> wrote:

> WITH RECURSIVE struc (pref, id, depth ) AS (
>   SELECT '', node, 1 from forest where node= 4
>   UNION ALL
>   SELECT (case when struc.pref= '' then '\' else struc.pref end )||
> '...' ,
>          node,
>          struc.depth +1
>   FROM forest JOIN struc ON parent=struc.id
>   )
>   SELECT * FROM struc;
>
>  (path,node,depth)
>            4  1
>   \...     5  2
>   \......  6  3
>
> This is fine as long as I start with a given node (here node= 4).
>
> But How can I retrieve the complete structure in one query ?

Start with parent is null in the first query (instead of 'where
node=4').

*untested*


Andreas
--
Really, I'm not out to destroy Microsoft. That will just be a completely
unintentional side effect.                              (Linus Torvalds)
"If I was god, I would recompile penguin with --enable-fly."   (unknown)
Kaufbach, Saxony, Germany, Europe.              N 51.05082°, E 13.56889°

Re: WITH RECURSIVE question

From
hubert depesz lubaczewski
Date:
On Fri, Jul 13, 2012 at 12:20:44PM +0200, Marc Mamin wrote:
> But How can I retrieve the complete structure in one query ?
> do I have to use a procedure for that ?
>
> Something like :
>
> WITH FOR_EACH (node) AS ( SELECT node from forest where parent IS NULL)
> SELECT * FROM (
>   WITH RECURSIVE struc (pref, id, depth ) AS (
>     SELECT '', node, 1 from forest where node= FOR_EACH.node
>     UNION ALL
>     SELECT (case when struc.pref= '' then '\' else struc.pref end )||
> '...' ,
>            node,
>            struc.depth +1
>     FROM forest JOIN struc ON parent=struc.id
>     )
>     SELECT * FROM struc
> )one_tree
> ;

You can run the query you showed, with just slight modification:

WITH RECURSIVE struc (pref, id, depth ) AS (
    SELECT '', node, 1 from forest where parent is null
    UNION ALL
    SELECT (case when struc.pref= '' then '\' else struc.pref end )||
    '...' ,
    node,
    struc.depth +1
    FROM forest JOIN struc ON parent=struc.id
)
SELECT * FROM struc;

But the result will most likely be *not* what you expected:

  pref   │ id │ depth
─────────┼────┼───────
         │  1 │     1
         │  4 │     1
 \...    │  2 │     2
 \...    │  5 │     2
 \...... │  3 │     3
 \...... │  6 │     3
(6 rows)

The problem is that you can't really order the rows in such a way that you wanted.

But check this:
http://www.depesz.com/2011/12/16/rtrees-recursive-trees-what-did-you-think-about/
Especially look for how "path" and "priority path" are constructed.

Best regards,

depesz

--
The best thing about modern society is how easy it is to avoid contact with it.
                                                             http://depesz.com/

Re: WITH RECURSIVE question

From
"Marc Mamin"
Date:
great,

many thanks for the excellent blog entry.

Marc Mamin


> -----Original Message-----
> From: depesz@depesz.com [mailto:depesz@depesz.com]
> Sent: Freitag, 13. Juli 2012 12:52
> To: Marc Mamin
> Cc: pgsql-general@postgresql.org
> Subject: Re: [GENERAL] WITH RECURSIVE question
> 
> On Fri, Jul 13, 2012 at 12:20:44PM +0200, Marc Mamin wrote:
> > But How can I retrieve the complete structure in one query ?
> > do I have to use a procedure for that ?
> >
> > Something like :
> >
> > WITH FOR_EACH (node) AS ( SELECT node from forest where parent IS
> NULL)
> > SELECT * FROM (
> >   WITH RECURSIVE struc (pref, id, depth ) AS (
> >     SELECT '', node, 1 from forest where node= FOR_EACH.node
> >     UNION ALL
> >     SELECT (case when struc.pref= '' then '\' else struc.pref end )||
> > '...' ,
> >            node,
> >            struc.depth +1
> >     FROM forest JOIN struc ON parent=struc.id
> >     )
> >     SELECT * FROM struc
> > )one_tree
> > ;
> 
> You can run the query you showed, with just slight modification:
> 
> WITH RECURSIVE struc (pref, id, depth ) AS (
>     SELECT '', node, 1 from forest where parent is null
>     UNION ALL
>     SELECT (case when struc.pref= '' then '\' else struc.pref end )||
>     '...' ,
>     node,
>     struc.depth +1
>     FROM forest JOIN struc ON parent=struc.id
> )
> SELECT * FROM struc;
> 
> But the result will most likely be *not* what you expected:
> 
>   pref   │ id │ depth
> ─────────┼────┼───────
>          │  1 │     1
>          │  4 │     1
>  \...    │  2 │     2
>  \...    │  5 │     2
>  \...... │  3 │     3
>  \...... │  6 │     3
> (6 rows)
> 
> The problem is that you can't really order the rows in such a way that
> you wanted.
> 
> But check this:
> http://www.depesz.com/2011/12/16/rtrees-recursive-trees-what-did-you-
> think-about/
> Especially look for how "path" and "priority path" are constructed.
> 
> Best regards,
> 
> depesz
> 
> --
> The best thing about modern society is how easy it is to avoid contact
> with it.
> 
> http://depesz.com/

Re: WITH RECURSIVE question

From
Chris Travers
Date:

Also this may be a bit more than you asked for but I just put up a blog entry a couple days going through CTE's generally and how we use them in LedgerSMB.  You might find it helpful.