2010-07-12 15 views
3

J'exécution d'une requête récursive dans Postgres pour récupérer une liste d'e-mails et leurs enfants taraudés comme suit:une commande AVEC requête récursive dans Postgres

WITH RECURSIVE cte (id, title, path, parent_id, depth) AS (
    SELECT id, 
      title, 
      array[id] AS path, 
      parent_id, 
      1 AS depth 
    FROM emails 
    WHERE parent_id IS NULL 

    UNION ALL 

    SELECT emails.id, 
      emails.title, 
      cte.path || emails.id, 
      emails.parent_id, 
      cte.depth + 1 AS depth 
    FROM emails 
      JOIN cte ON emails.parent_id = cte.id 
) 
SELECT id, title, path, parent_id, depth FROM cte 
ORDER BY path; 

Comment irait de changer l'ordre de la liste (par exemple trier sur le titre) avant de trouver des courriels pour enfants. J'ai évidemment besoin de garder l'ORDER BY externe pour que la liste soit récupérée dans son ordre d'arbre, et Postgres ne me laissera pas insérer une clause ORDER BY avant l'UNION ALL.

Merci,

Répondre

2

Créer une vue comprenant la première partie de votre requête, commandé par titre. Peut-être quelque chose comme ça?

 CREATE VIEW title_Sort AS 
     SELECT id, 
     title, 
     array[id] AS path, 
     parent_id, 
     1 AS depth 
     FROM emails 
     WHERE parent_id IS NULL 
     ORDER BY title; 

Ensuite, UNION TOUS cette vue avec votre autre requête comme vous le faisiez auparavant. Je pense que cela fonctionnera. Sur mon netbook en ce moment donc je ne peux pas tester:/

+0

Malheureusement, ce doesn ne fonctionne pas. Votre méthode me permet de faire le ORDER BY dans la première requête, mais le chemin ORDER BY à la fin le remplacera toujours - le résultat étant que la liste est essentiellement ordonnée par id. – robdog

+0

Hm, alors je ne suis pas sûr de ce que vous demandez ... le dernier ORDER BY provoquera toujours l'ordre de la table résultante par le chemin. De quoi avez-vous besoin pour le commander à mi-requête? Qu'est-ce que vous essayez de faire qui est tributaire de l'ordre? – rownage

+0

Je voudrais récupérer une liste de courriels filetés, en maintenant leur structure arborescente - ce que la requête ci-dessus me permet de faire - et être capable de trier les éléments de premier niveau par titre. – robdog

1

Ceci est non testé, mais généralement je peux ajouter ORDER BY avant une union tant qu'il ya entre parenthèses ...

WITH RECURSIVE cte (id, title, path, parent_id, depth) AS (
( SELECT id, 
      title, 
      array[id] AS path, 
      parent_id, 
      1 AS depth 
    FROM emails 
    WHERE parent_id IS NULL 
    ORDER BY title 
) 
    UNION ALL 

    SELECT emails.id, 
      emails.title, 
      cte.path || emails.id, 
      emails.parent_id, 
      cte.depth + 1 AS depth 
    FROM emails 
      JOIN cte ON emails.parent_id = cte.id 
) 
SELECT id, title, path, parent_id, depth FROM cte 
ORDER BY path;