PostgreSQL查询JSON分组报错:无法识别相等运算符求解
解决PostgreSQL分组JSON字段报错并获取车辆最新停靠位置的问题
我来帮你搞定这个问题!你遇到的ERROR: could not identify an equality operator for type JSON,本质是PostgreSQL的原生JSON类型没有默认的相等比较运算符,所以当你把position(JSON类型)放到GROUP BY里时,数据库没法判断两个JSON值是否相等,自然就报错了。而且你的原查询还有个逻辑问题:子查询select * from "Config.Tracking" ORDER BY date DESC LIMIT 1是取整个位置表的最后一条记录,不是对应每个车辆会话的最新位置,这也会导致结果不符合预期。
下面给你两种靠谱的解决方案,优先推荐第一种:
方案一:用窗口函数筛选每个会话的最新位置(最优解)
这种方法完全避开了对JSON字段的分组操作,直接通过窗口函数定位每个sessionId对应的最新位置记录,逻辑更清晰,性能也更优:
SELECT v."plateNumber", v."vehicleId", t.position FROM "Config.Vehicle" v INNER JOIN "Config.Session" s ON s."vehicleId" = v."vehicleId" INNER JOIN ( -- 给每个会话的位置记录按时间倒序排号,取第一条(最新的) SELECT "sessionId", position, ROW_NUMBER() OVER (PARTITION BY "sessionId" ORDER BY date DESC) AS rn FROM "Config.Tracking" ) t ON t."sessionId" = s."sessionId" AND t.rn = 1 -- 只保留每个会话的最新位置 WHERE s."sessionEnd" IS NOT NULL;
方案二:转换JSON为可比较的类型(仅作补充)
如果你一定要用GROUP BY的方式,可以把JSON类型转换为JSONB类型(PostgreSQL对JSONB支持相等比较),但注意要先修正子查询的逻辑问题:
SELECT v."plateNumber", v."vehicleId", t.position::jsonb AS position FROM "Config.Vehicle" v INNER JOIN "Config.Session" s ON s."vehicleId" = v."vehicleId" INNER JOIN ( SELECT "sessionId", position FROM ( SELECT "sessionId", position, ROW_NUMBER() OVER (PARTITION BY "sessionId" ORDER BY date DESC) AS rn FROM "Config.Tracking" ) sub WHERE rn = 1 ) t ON t."sessionId" = s."sessionId" WHERE s."sessionEnd" IS NOT NULL GROUP BY 1, 2, t.position::jsonb;
不过说实话,方案二有点画蛇添足,因为窗口函数已经帮我们筛选出了唯一的最新记录,根本不需要再GROUP BY了,所以优先用方案一就好。
内容的提问来源于stack exchange,提问作者xyz83242
相关产品推荐
相关产品推荐

