从包含路径的表生成 JSON 树对象

问题描述 投票:0回答:1

给定一个包含未知树结构的路径/节点的表:

| id | path_id | node
| 1  | p1      | n1
| 2  | p1      | n2
| 3  | p1      | n3
| 4  | p2      | n1
| 5  | p2      | n2
| 6  | p2      | n4

对应的树结构为:

    n1 
   /  
  n2
 /  \
n3   n4

是否可以使用 SQL 和 PostgreSQL 函数为该树生成 JSON 对象?

sql json postgresql tree
1个回答
3
投票

看起来你有一个路径列表,其中部分重叠。

2024 年更新

使用

jsonb
jsonb_object_agg()
,产生更密集的结果,其中每条边都是一个键/值对。

jsonb
开箱即用地删除重复的键值。不需要
DISTINCT

SELECT jsonb_object_agg(node, parent) AS edges
FROM  (
   SELECT node, lag(node) OVER (PARTITION BY path_id ORDER BY id) AS parent
   FROM   tbl
   ORDER  BY parent NULLS FIRST, node  -- ORDER BY optional
   ) sub;

jsonb_object_agg_strict()
还可以删除具有空值的对象,有效地修剪根部的悬垂边缘:

SELECT jsonb_object_agg_strict(node, parent) AS edges
FROM  (
   -- same as above
   ) sub;

2014年原始答案

旧版

json
解决方案。首先删除重复的边缘,因为
json
保留所有对象,甚至重复的键。

SELECT DISTINCT
       node, lag(node) OVER (PARTITION BY path_id ORDER BY id) AS parent
FROM   tbl
ORDER  BY parent NULLS FIRST, node;  -- ORDER BY optional
对于根节点,

parent
为 NULL。您可能想从结果中删除这个“非边缘”。
然后,要“为这棵树生成一个 JSON 对象”,您可以使用
json_agg()
:

SELECT json_agg(sub) AS edges
FROM  (
   SELECT DISTINCT
          node, lag(node) OVER (PARTITION BY path_id ORDER BY id) AS parent
   FROM   tbl
   ORDER  BY parent NULLS FIRST, node  -- ORDER BY optional
   ) sub;

小提琴
sqlfiddle

© www.soinside.com 2019 - 2024. All rights reserved.