PostgreSQL查询报错:无法识别json[]类型的相等运算符
解决PostgreSQL中
json[]类型无法GROUP BY的问题 嘿,这个问题我之前碰到过!报错的核心原因很直接:PostgreSQL没有为json[](JSON数组类型)内置相等比较运算符,而GROUP BY操作需要能判断两个值是否相等来分组,所以数据库不知道怎么处理json[]的分组,就抛出了这个错误。
另外先提两个你原查询里的小问题,不然即使解决了运算符问题,也可能出其他错:
- 你的子查询里没加
GROUP BY id,这会把整个private_table的行都聚合成一个数组,id值也会是随机的,完全不符合关联some_table的预期,必须补上GROUP BY id。 SELECT里的some_data没在GROUP BY里,PostgreSQL默认要求非聚合列必须出现在GROUP BY里,所以要么把它加进去,要么用聚合函数(比如MAX(some_data))处理它。
接下来给你几个靠谱的解决方案,按推荐程度排序:
方法1:转成jsonb[]类型(最推荐)
PostgreSQL为jsonb[](JSONB数组类型)内置了相等运算符,所以我们可以把生成的数组转成jsonb[]类型。修改后的SQL如下:
SELECT some_data, new_table.data FROM some_table JOIN ( SELECT array_agg( jsonb_build_object( -- 改用jsonb_build_object生成JSONB对象 'id', food_item.id, 'name', name, 'fiber', fiber * (serving->>'scaling_factor')::real, 'serving', serving ) ) AS data, -- 聚合结果自然是jsonb[]类型 id FROM private_table GROUP BY id -- 必须加的分组,确保每个id对应自己的数组 ) new_table ON new_table.id = some_table.id WHERE time = '12:00' GROUP BY new_table.data, some_data; -- 把some_data也加入分组
jsonb本身比json性能更好,支持更多操作,用这个方案不仅解决了分组问题,还能获得更好的长期扩展性。
方法2:将JSON数组转成字符串分组
如果你不想切换到jsonb,可以把json[]转成字符串,用字符串的相等比较来分组。注意要选一个不会在JSON内容里出现的分隔符:
SELECT some_data, new_table.data FROM some_table JOIN ( SELECT array_agg( json_build_object( 'id', food_item.id, 'name', name, 'fiber', fiber * (serving->>'scaling_factor')::real, 'serving', serving ) ) AS data, id FROM private_table GROUP BY id ) new_table ON new_table.id = some_table.id WHERE time = '12:00' GROUP BY array_to_string(new_table.data, '###'), new_table.data, some_data;
这个方案的风险是如果JSON内容里出现了你选的分隔符(比如###),会导致错误的分组判断,所以只适合你能确保分隔符唯一的场景。
方法3:用哈希值分组
可以把json[]转成文本后生成哈希值,用哈希值来做分组判断(哈希碰撞概率极低,大部分场景下可靠):
SELECT some_data, new_table.data FROM some_table JOIN ( SELECT array_agg( json_build_object( 'id', food_item.id, 'name', name, 'fiber', fiber * (serving->>'scaling_factor')::real, 'serving', serving ) ) AS data, id FROM private_table GROUP BY id ) new_table ON new_table.id = some_table.id WHERE time = '12:00' GROUP BY md5(new_table.data::text), new_table.data, some_data;
这个方案不需要改数据类型,但哈希值不能完全替代真实的相等判断,适合对性能要求不高且碰撞风险可接受的场景。
内容的提问来源于stack exchange,提问作者Ted
相关产品推荐
相关产品推荐

