I have the following recursive function in PostgreSQL. but I wonder how it works
- the sequence of execution (it goes deep hierarchy by each root node first or list all root node first then go to next level.)
- how it breaks from this function.
Can anyone help me explain this?
CREATE OR REPLACE FUNCTION build_hierarchey(location_id int) RETURNS SETOF jsonb
AS $BODY$
BEGIN
RETURN QUERY
SELECT
CASE WHEN COUNT(x) > 0
THEN ((to_jsonb(t) || jsonb_build_object('Children', jsonb_agg(f.x)))
ELSE to_jsonb(t)
END
FROM "Locations" t
LEFT JOIN build_hierarchey(t."Id") AS f(x) ON true
WHERE t."ParentLocationId" = location_id OR (location_id IS null AND t."ParentLocationId" IS null)
GROUP BY t."Id", t."Name";
END;
$BODY$ LANGUAGE 'plpgsql'
this is how I use it.
select jsonb_agg(build_hierarchey) from build_hierarchey(null::int)
Result in json (hirarchey)
[
{
"Id": 11,
"Name": "Zone-C",
"Children": [
{
"Id": 23,
"Name": "01-C",
"CategoryId": null
},
{
"Id": 20,
"Name": "01-A",
"CategoryId": null
}
],
"CategoryId": null
},
{
"Id": 19,
"Name": "Zone-K",
"CategoryId": null
},
{
"Id": 1,
"Name": "ccc",
"Children": [
{
"Id": 3,
"Name": "01-A",
"CategoryId": null
},
{
"Id": 5,
"Name": "01-C",
"Children": [
{
"Id": 8,
"Name": "01-C-03",
"CategoryId": null
},
{
"Id": 7,
"Name": "01-C-02",
"CategoryId": null
},
{
"Id": 6,
"Name": "01-C-01",
"CategoryId": null
}
],
"CategoryId": null
},
{
"Id": 4,
"Name": "01-B",
"CategoryId": null
}
],
"CategoryId": null
},
{
"Id": 18,
"Name": "Zone-J",
"CategoryId": null
},
{
"Id": 2,
"Name": "Zone-B",
"Children": [
{
"Id": 10,
"Name": "02-A",
"CategoryId": null
},
{
"Id": 9,
"Name": "01-A",
"CategoryId": null
}
],
"CategoryId": null
},
{
"Id": 16,
"Name": "Zone-H",
"CategoryId": null
},
{
"Id": 15,
"Name": "Zone-G",
"CategoryId": null
},
{
"Id": 14,
"Name": "Zone-F",
"CategoryId": null
},
{
"Id": 17,
"Name": "Zone-I",
"CategoryId": null
},
{
"Id": 22,
"Name": "Zone-AA",
"CategoryId": null
}
]
Here is the "Locations" table. (self-referencing)
SELECT "Id", "Name", "ParentLocationId" FROM "Locations"
ID Name ParentLocationId
1 "ccc"
2 "Zone-B"
3 "01-A" 1
4 "01-B" 1
5 "01-C" 1
6 "01-C-01" 5
7 "01-C-02" 5
8 "01-C-03" 5
9 "01-A" 2
10 "02-A" 2
11 "Zone-C"
14 "Zone-F"
15 "Zone-G"