2010-09-14 11 views
7

Je sorcière de table contient les champs: id, id_parent, nom (etc.)lignes SELECT de table à l'aide pour l'arbre

Je veux commander ce tableau dans « l'ordre de Voyage d'arbre », à savoir.

id parent_id 
1, 0 
3, 1 
5, 1 

2, 0 
8, 2 

4, 0 
9, 4 

(...)

en bref décrire: prendre nœud racine, ajoutez tous les enfants, prendre racine nœud suivant append enfants, etc.

Répondre

10

par votre description Je suppose que vous voulez dire en largeur premier ordre, ce qui pourrait être fait à l'aide d'une easly AVEC requête récursive (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; 

Vous pouvez également utiliser en profondeur d'abord pour ce qui suit à l'aide 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; 
+0

Thx pour cela, je n'étais pas au courant des requêtes WITH existantes dans Postgres – canni

+0

Je pense que nous ne pouvons pas utiliser l'instruction UNION dans la clause WITH – Fer

+1

Votre solution pour profondeur-premier ordre ne fonctionnera pas pour id avec un nombre différent de chiffres. – synergetic

-2
SELECT * FROM table ORDER BY id,parent_id 

Cela devrait commander mes colonnes dans la ordre là placé dans la requête.

À moins que vous voulez dire regrouper les éléments, sorcière je pense que vous faites, puis utilisez

SELECT * FROM table ORDER BY id GROUP BY parent_id 

Et je vous conseille également de lire cet article: http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

+0

Cela ne produira pas les résultats dans l'ordre que je veux ... – canni

+0

Cela produira une erreur de syntaxe dans Postgres (champ id doit être utilisé dans la fonction agrégée), ce n'est pas MySQL :) – canni

+0

Ahh ok, désolé, je pensais que cela aurait fonctionné sous 'postgres', je ne suis pas aussi bon avec ça. – RobertPitt

0

Vous pouvez également utiliser l'excellent module de LTree, mais vous devez réorganiser vos données un peu.

4

Comme remarqué par synergétique, la solution de l'ordre de profondeur d'abord fournie par Diogo Biazus ne fonctionnera pas pour id avec nombre différent de chiffres.

Mais vous pouvez utiliser cette solution à la place, qui utilise des tableaux de nombre entier:

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;