如何将多个postgreSQL表嵌套到一个json中?

如何将多个postgreSQL表嵌套到一个json中?,json,postgresql,Json,Postgresql,我刚开始使用postgreSQL,现在我正在尝试获取相关表项的树结构 例如,我有以下表格: 街道、物业、建筑物、楼层、房间 streets (columns: id, name) properties (columns: id, name, street_id) buildings (columns: id, name, property_id) floors (columns: id, name, building_id) rooms (columns: id, name, floor_id)

我刚开始使用postgreSQL,现在我正在尝试获取相关表项的树结构

例如,我有以下表格:

街道、物业、建筑物、楼层、房间

streets (columns: id, name)
properties (columns: id, name, street_id)
buildings (columns: id, name, property_id)
floors (columns: id, name, building_id)
rooms (columns: id, name, floor_id)
现在我尝试获得如下输出:

[{
"id":1,
"name":"Main Street",
"properties": [{
     "id":"1",
     "name":"First Property",
     "buildings": [{
          "id":"1",
          "name":"Main Building",
          "floors": [{...},{...}]
        },{
          "id":"2",
          "name":"Shed",
          "floors": [{...},{...}]
        }]
   },{
     "id":"2",
     "name":"Another Property",
     "buildings": [{...},{...}]
   }]
}]
目前的查询如下:

SELECT s.*, json_agg(p.*) as properties
FROM streets AS s 
INNER JOIN properties AS p ON s.id = p.street_id
GROUP BY s.id; 
这为我提供了上述两层街道的输出以及街道内的属性结果。但是我不知道如何将建筑物嵌套到物业中,然后将楼层嵌套到建筑物中

我可以为它们添加另一个内部连接和json_agg(),但是它们不会在属性中

有什么建议我应该如何处理这个问题吗

编辑:

谢谢,德米特里,你的回答很好。但是现在让我们假设我想将所有数据存储在同一个名为“locations”的表中,并通过“parent_id”链接条目

因此,我有以下专栏:

id、名称、类型、父\u id

使用下面的代码,我得到了错误的层次结构

WITH RECURSIVE locationtree AS (
   SELECT
      e.*,
      null::json as parent
   FROM location e
   WHERE parent_id IS NULL

   UNION ALL

   SELECT
      e.*,
      row_to_json(et.*) as parent
   FROM location e
   INNER JOIN locationtree et
      ON et.id = e.parent_id
)
SELECT *
FROM locationtree;
这导致 房间 地板 建筑 财产 街头

但我想像最初的问题和Dmitry的回答一样 街道 性质 建筑 地板 房间

关于使用表达式查询的任何建议如下所示:

WITH floors_agg AS (
    -- get floors with nested rooms
    SELECT 
      f.*,
      json_agg(r.*) nested_rooms 
    FROM floors f
      LEFT JOIN rooms r ON r.floor_id = f.id
    GROUP BY 1
), buildings_agg AS (
    -- get buildings with nested floors
    SELECT 
      b.*,
      json_agg(fa.*) nested_floors 
    FROM buildings b
      LEFT JOIN floors_agg fa ON fa.building_id = b.id
    GROUP BY 1
), properties_agg AS (
    -- get properties with nested buildings
    SELECT
      p.*,
      json_agg(ba.*)
    FROM properties p
      LEFT JOIN buildings_agg ba ON ba.property_id = p.id
    GROUP BY 1
), streets_agg AS (
  -- get streets with nested properties
    SELECT
      s.*,
      json_agg(pa.*) nested_properties
    FROM streets s
      LEFT JOIN properties_agg pa ON pa.street_id = s.id
    ORDER BY 1
)
SELECT json_agg(sa.*)
FROM streets_agg sa;
使用表达式,查询可能如下所示:

WITH floors_agg AS (
    -- get floors with nested rooms
    SELECT 
      f.*,
      json_agg(r.*) nested_rooms 
    FROM floors f
      LEFT JOIN rooms r ON r.floor_id = f.id
    GROUP BY 1
), buildings_agg AS (
    -- get buildings with nested floors
    SELECT 
      b.*,
      json_agg(fa.*) nested_floors 
    FROM buildings b
      LEFT JOIN floors_agg fa ON fa.building_id = b.id
    GROUP BY 1
), properties_agg AS (
    -- get properties with nested buildings
    SELECT
      p.*,
      json_agg(ba.*)
    FROM properties p
      LEFT JOIN buildings_agg ba ON ba.property_id = p.id
    GROUP BY 1
), streets_agg AS (
  -- get streets with nested properties
    SELECT
      s.*,
      json_agg(pa.*) nested_properties
    FROM streets s
      LEFT JOIN properties_agg pa ON pa.street_id = s.id
    ORDER BY 1
)
SELECT json_agg(sa.*)
FROM streets_agg sa;

哇,这正是我想要的。现在看起来很容易……)但假设现在我将所有数据存储在同一个表中,表中有父id,因此街道、物业、建筑物、楼层、房间都存储在一个名为location的表中,表中有“id”、“name”、“type”、“parent\u id”列。我将如何获取该树?@sking
街道与agg
(或最初定义的表)之间的关系是什么和
位置
表格
location.id=streets.location\u id
?我不知道你的意思。我的第二个问题是,当我将所有信息存储在一个表中时,如何获得与您的结果相同的输出。因此,我会删除街道、物业、建筑物、楼层、房间等表格,而是创建一个具有位置的新表格。这将包含所有街道、建筑物、财产、楼层和房间名称。。所以条目应该是{ID:1,name:Main Street,type:Street,parent_ID:null}{ID:2 name:school ground,type:property,parent_ID:1}….哇,这就是我想要的。现在看起来很容易……)但假设现在我将所有数据存储在同一个表中,表中有父id,因此街道、物业、建筑物、楼层、房间都存储在一个名为location的表中,表中有“id”、“name”、“type”、“parent\u id”列。我将如何获取该树?@sking
街道与agg
(或最初定义的表)之间的关系是什么和
位置
表格
location.id=streets.location\u id
?我不知道你的意思。我的第二个问题是,当我将所有信息存储在一个表中时,如何获得与您的结果相同的输出。因此,我会删除街道、物业、建筑物、楼层、房间等表格,而是创建一个具有位置的新表格。这将包含所有街道、建筑物、财产、楼层和房间名称。。所以条目应该是{ID:1,name:Main Street,type:Street,parent_ID:null}{ID:2 name:school ground,type:property,parent_ID:1}。。。。