2016-06-17 5 views
2

Ich muss eine SQL-Abfrage erstellen (Postgres 9.5.3), die ein hierarchisches JSON-Ergebnis zurückgibt. Dies ist der Code, den ich bisher geschriebenReturn json Hierarchische Struktur in einer einzigen SQL-Abfrage

WITH RECURSIVE q AS ( 
    WITH c AS (
     SELECT pc."Id", pc."Description" 
     FROM "ProductCategories" pc 
     WHERE pc."Active" = true 
    ) 
    SELECT pc, ARRAY[c] as "Children", ARRAY[pc."Id"] as "Path" 
    FROM "ProductCategories" pc 
    LEFT JOIN c ON pc."Id" = c."Id" 
    WHERE NULLIF(pc."ParentId", 0) IS NULL 
    AND pc."Active" = true 
    UNION ALL 
    SELECT pc_descendant, array_append(q."Children", c), q."Path" || pc_descendant."Id" 
    FROM q 
    JOIN "ProductCategories" pc_descendant ON pc_descendant."ParentId" = (q.pc)."Id" 
    LEFT JOIN c ON pc_descendant."Id" = c."Id" 
    WHERE pc_descendant."Active" = true 
) 
SELECT * FROM q 

I Problem habe Children hierarchisches Objekt zu erstellen. Für diese Struktur

A 
    B 
     C 
D 
    E 

die array_append Funktionen scheint Kinder Elemente in einzelnen Array anhängen:

A.Children = [ {B}, {C}, {D} ] //for category A 

Ich brauche Struktur:

A.Children = [ {B, Children = [ {C, Children = [ {D} ] } ] } ] 

Wie kann ich meine Abfrage ändern, um dies zu erreichen, ? Mit freundlichen Grüßen

Antwort

2

Nicht sicher, dass es zumindest auf die einfache bequeme Weise möglich ist.

Es scheint jedoch, dass es einfach ist, "echte" Rekursion zu verwenden. Hier

ist einfaches Beispiel:

create temp table t(id int, parent int, name text) on commit drop; 

insert into t values 
    (1,null,'john'), 
    (2,1,'jane'), 
    (3,1,'jack'), 
    (4,2,'julian'); 

create or replace function build_family(p_parent int) returns setof jsonb as $$ 

    select jsonb_build_object('name', t.name, 'family', jsonb_agg(f.x)) 
    from t left join build_family(t.id) as f(x) on true 
    where t.parent = p_parent or (p_parent is null and t.parent is null) 
    group by t.id, t.name; 

$$ language sql; 

select * from build_family(null::int); 

und Ergebnis ist

{"name": "john", "family": [{"name": "jane", "family": [{"name": "julian", "family": [null]}]}, {"name": "jack", "family": [null]}]} 

Ich hoffe, dass Sie es für Ihre Daten anpassen können.

Viel Glück.