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
相关产品推荐
相关产品推荐

