You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL中如何将关联表记录转为单字段JSON数组(去除f1)

解决PostgreSQL关联表JSON数组返回多余f1字段的问题

我懂你遇到的糟心事——用row(p)构造行的时候,PostgreSQL会把整个子查询结果打包成一个单元素复合类型,这个元素的默认字段名就是f1,转成JSON后自然就多出了这个没必要的键。下面给你几个优化方案,从简洁到灵活都有:

1. 最省心的方案:用json_agg()直接聚合

PostgreSQL专门提供了json_agg()函数,能直接把多行数据聚合成JSON数组,完全不需要手动嵌套array_agg()+array_to_json(),还能完美保留原表的字段名,彻底告别f1:

select grouped_by_table.json_array as my_col 
from profiles 
left join ( 
    select p.profile_id, json_agg(p) as json_array 
    from positions p 
    group by profile_id 
) as grouped_by_table on grouped_by_table.profile_id::int = profiles.id

这个查询里,json_agg(p)会直接把positions表的每一行转成JSON对象,再聚合成一个干净的JSON数组,结果就是你想要的格式。

2. 兼容原逻辑的优化:替换row(p)为to_json(p)

如果你想保留原来的array_agg()+array_to_json()组合逻辑,只需要把row(p)换成to_json(p)就行——to_json(p)会直接把整行转成JSON对象,不会额外包装成单元素复合类型:

select grouped_by_table.json_array as my_col 
from profiles 
left join ( 
    select p.profile_id, array_to_json(array_agg(to_json(p))) as json_array 
    from positions p 
    group by profile_id 
) as grouped_by_table on grouped_by_table.profile_id::int = profiles.id

3. 按需定制的灵活方案:用json_build_object()

如果你不需要positions表的所有字段,只想返回指定字段,可以用json_build_object()手动构造JSON结构,既能精准控制返回内容,也能彻底避免多余字段:

select grouped_by_table.json_array as my_col 
from profiles 
left join ( 
    select p.profile_id, 
           json_agg(
               json_build_object(
                   'id', p.id, 
                   'title', p.title, 
                   'company', p.company  -- 替换成你实际需要的字段
               )
           ) as json_array 
    from positions p 
    group by profile_id 
) as grouped_by_table on grouped_by_table.profile_id::int = profiles.id

原查询为啥会出现f1?

原查询里的row(p)是把整个p行(子查询的结果)当作单个元素传入row()函数,PostgreSQL会自动给这个元素分配默认字段名f1,转成JSON后就变成了{"f1": {...}}的嵌套结构。上面的方案都是直接处理行本身,不会产生这个多余的包装层。

内容的提问来源于stack exchange,提问作者tim_xyz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:08:17