我在postgres 11.4数据库中有一个表,具有自引用树结构:
+------------+
| account |
+------------+
| id |
| code |
| type |
| parentId | -- references account.id
+------------+
每个孩子都可以有另一个孩子,嵌套级别没有限制。
我想从中生成一个json对象,嵌套所有子对象(resursivly)。
用一个查询就可以解决这个问题吗?或者任何其他使用typeorm和一个表的解决方案?
否则我将不得不在服务器端手动绑定数据。
我尝试了以下查询:
SELECT account.type, json_agg(account) as accounts
FROM account
-- LEFT JOIN "account" "child" ON "child"."parentId"="account"."id" -- tried to make one column child
GROUP BY account.type
结果:
[
...
{
"type": "type03",
"accounts": [
{
"id": 28,
"code": "acc03.001",
"type": "type03",
"parentId": null
},
{
"id": 29,
"code": "acc03.001.001",
"type": "type03",
"parentId": 28
},
{
"id": 30,
"code": "acc03.001.002",
"type": "type03",
"parentId": 28
}
]
}
...
]
我希望这样:
[
...
{
"type": "type03",
"accounts": [
{
"id": 28,
"code": "acc03.001",
"type": "type03",
"parentId": null,
"child": [
{
"id": 29,
"code": "acc03.001.001",
"type": "type03",
"parentId": 28
},
{
"id": 30,
"code": "acc03.001.002",
"type": "type03",
"parentId": 28
}
]
}
]
}
...
]
1条答案
按热度按时间jutyujz01#
这很棘手(除非我错过了一些重要的东西,我对此表示怀疑。)
这是一个递归问题,但是标准的递归cte没有能力处理它,因为我们需要在每个级别上进行聚合,而cte不允许在递归项中进行聚合。
我用pl/pgsql函数解决了这个问题:
调用(精确返回所需结果):
db<>在这里摆弄-使用扩展的测试用例
我选择了钥匙的名字
children
而不是child
,因为可以嵌套多个。jsonb_pretty()
美化显示器是可选的。这是假定参照完整性;应使用fk约束实现。
对于您的特定情况,使用
code
列-如果它显示(未公开)有用的属性。就像我们可以在没有rcte和添加临时表的情况下导出嵌套级别一样t
. 但我的目标是一个基于id引用的通用解决方案。函数中有很多内容。我添加了内联注解。基本上,它是这样做的:
创建添加了嵌套级别的临时表(
lvl
)如果找不到嵌套,则返回简单结果
如果发现嵌套,则折叠到
jsonb
从顶部嵌套层向下。将所有中间结果写入第二个临时表
j
.一旦我们到达第二个嵌套级别,返回完整的结果。
函数需要
_type
作为参数,仅返回给定类型。否则,整个表都会被处理。旁白:避免混合大小写标识符,如
"parentId"
如果可能的话。请参见:postgresql列名是否区分大小写?