8

I have table witch contains fields: id, parent_id, name (etc.)

i want to order this table in "tree travel order" ie.

id  parent_id
1,  0
3,  1
5,  1

2,  0
8,  2

4,  0
9,  4

(...)

in short describe: take root node, append all children, take next root node append children etc.

4 Answers 4

10

By your description I assume you mean breadth-first order, which could be easly done using a WITH RECURSIVE query (PostgreSQL 8.4+):

WITH RECURSIVE tree 
AS 
(
    SELECT 
        node_name, id, parent_id, NULL::varchar AS parent_name 
    FROM foo 
    WHERE parent_id IS NULL 
    UNION
    SELECT 
        node_name, f1.id, f1.parent_id, tree.node_name AS parent_name 
    FROM 
        tree 
        JOIN foo f1 ON f1.parent_id = tree.id
) 
SELECT node_name, empno, parent_id, node_name FROM tree;

You could also use depth-first order using the following SQL:

WITH RECURSIVE tree 
AS 
(
    SELECT 
        node_name, id, parent_id, NULL::varchar AS parent_name, id::text AS path 
    FROM foo WHERE parent_id IS NULL 
    UNION
    SELECT 
        node_name, f1.id, f1.parent_id, tree.node_name AS parent_name, tree.path || '-' || f1.id::text AS path 
    FROM 
        tree 
        JOIN foo f1 ON f1.parent_id = tree.id
) 
SELECT node_name, empno, parent_id, node_name, path FROM tree ORDER BY path;
Sign up to request clarification or add additional context in comments.

3 Comments

Thx for that, i was not aware of existing WITH queries in Postgres
I think we can not use UNION statement in WITH clause
Your solution for depth-first order won't work for id's with different number of digits.
6

As noticed by synergetic, the solution for depth-first order provided by Diogo Biazus won't work for id's with different number of digits.

But you can use this solution instead, that uses arrays of integer :

WITH RECURSIVE tree 
AS 
(
    SELECT 
        node_name, id, parent_id, NULL::varchar AS parent_name, array[id] AS path 
    FROM foo WHERE parent_id IS NULL 
    UNION
    SELECT 
        node_name, f1.id, f1.parent_id, tree.node_name AS parent_name, tree.path || f1.id AS path 
    FROM 
        tree 
        JOIN foo f1 ON f1.parent_id = tree.id
) 
SELECT node_name, empno, parent_id, node_name, path FROM tree ORDER BY path;

Comments

0

You can also use the excellent LTree module, but you need to reorganise your data a bit.

Comments

-2
SELECT * FROM table ORDER BY id,parent_id

That should order my columns in the order there placed within the query.

Unless you mean GROUP the items, witch I think you do, then use

SELECT * FROM table ORDER BY id GROUP BY parent_id

And i also advise you to read this article: http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

6 Comments

This will produce syntax error in Postgres (id field must be used in aggregate function), this is not MySQL :)
Ahh ok, sorry, I thought that would have worked under postgres, im not as good with it.
Would this work under psotgress SELECT * FROM table ORDER BY id || id ASC, parent_id ASC ?
this produces: ERROR: operator does not exist: integer || integer ; || is string catenation operator in postgres
This is what i was reading: maybe it would be better for you to take a look: archives.postgresql.org/pgsql-sql/2007-08/msg00079.php
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.