Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PostgreSQL recursive with

I need help with a recursive query. Assuming the following table:

CREATE TEMPORARY TABLE tree (
    id        integer PRIMARY KEY,
    parent_id integer NOT NULL,
    name      varchar(50)
);    

INSERT INTO tree (id, parent_id, name) VALUES (3, 0, 'Peter'), (2,0, 'Thomas'), (5,2, 'David'), (1, 0, 'Rob'), (8, 0, 'Brian');

I can retrieve a list of all people and their children with the following query:

WITH RECURSIVE recursetree(id, parent_id) AS (
    SELECT id, parent_id FROM tree WHERE parent_id = 0
  UNION
    SELECT t.id, t.parent_id
    FROM tree t
    JOIN recursetree rt ON rt.id = t.parent_id
  )
SELECT * FROM recursetree;

How can I list them in order, and also sort the first level items by name? For example, the desired output would be:

id, parent_id, name    
8, 0, "Brian"
3, 0, "Peter"
1, 0; "Rob"
2, 0, "Thomas"
5, 2, "  David"

Thanks,

**EDIT. Please note that adding an ORDER BY won't work: **

WITH RECURSIVE recursetree(id, parent_id, path, name) AS (
    SELECT 
        id, 
        parent_id, 
        array[id] AS path, 
        name 
    FROM tree WHERE parent_id = 0
  UNION ALL
    SELECT t.id, t.parent_id, rt.path || t.id, t.name
    FROM tree t
    JOIN recursetree rt ON rt.id = t.parent_id
  )
SELECT * FROM recursetree ORDER BY path;

The above will retain the parent child relationship (children follow their parents), but applying any other ORDER BY clause (ie: name - like some have suggested) will cause the result to lose it's parent-child relationships.

like image 791
robdog Avatar asked Jul 22 '10 09:07

robdog


People also ask

What is with recursive in PostgreSQL?

PostgreSQL provides the WITH statement that supports the designing of auxiliary queries also known as CTEs (Common Table Expressions). A recursive query is a query that refers to a recursive CTE.

WHAT IS WITH clause in PostgreSQL?

WITH provides a way to write auxiliary statements for use in a larger query. These statements, which are often referred to as Common Table Expressions or CTE s, can be thought of as defining temporary tables that exist just for one query.

How do I create a hierarchical query in PostgreSQL?

CONNECT BY, PRIOR and START WITH in Oracle In Oracle, the hierarchical query is defined using the two mandatory keywords i.e. CONNECT BY and START WITH. The hierarchy is built when the CONNECT BY defines the relationship between parent and child, the PRIOR keyword used with CONNECT by specifies the parent.

Can we use with statement in PostgreSQL?

You can use data-modifying statements (INSERT, UPDATE or DELETE) in WITH. This allows you to perform several different operations in the same query.


1 Answers

See also this (translated) article about CTE's in PostgreSQL: wiki.phpfreakz.nl

Edit: Try this one, using an array:

WITH RECURSIVE recursetree(id, parent_ids, firstname) AS (
    SELECT id, NULL::int[] || parent_id, name FROM tree WHERE parent_id = 0
  UNION ALL
    SELECT 
    t.id, 
    rt.parent_ids || t.parent_id, 
    name
    FROM tree t
    JOIN recursetree rt ON rt.id = t.parent_id
  )
SELECT * FROM recursetree ORDER BY parent_ids;
like image 62
Frank Heikens Avatar answered Sep 19 '22 17:09

Frank Heikens