7

我需要Postgres 9.2 中UNION ALL的一个JSON专栏。但是 Postgres 回复了这个错误:

ERROR: could not identify an equality operator for type json SQL  
state: 42883  
Character: 9

到查询:

(select cast('{"billingcode" : "' || billingcode || '"}' as JSON)
 from billing_2012_08 limit 10)
union
(select cast('{"charged" : "' || charged || '"}' as JSON)
 from sending_response_2012_08 limit 10)

这里有什么问题?

Postgres 似乎没有json数据类型的相等运算符。
如果这是正确的,为什么?

作为一个试图找出问题的例子,这很好用:

(select cast('{"billingcode" : "' || billingcode || '"}' as JSON)
 from billing_2012_08 limit 10)
union all
(select cast('{"charged" : "' || charged || '"}' as JSON)
 from sending_response_2012_08 limit 10)

请注意,UNION ALL只是“添加”结果,而不是仅仅UNION消除重复值。

4

1 回答 1

11

测试 JSON 值是否“相等”并非易事。除此之外,属性可以按任何顺序排序,或者可以有任何数量的无关紧要的空白。因此二进制或文本表示可以完全不同,而根据 JSON 规范,值仍然是相等的。这就是为什么PostgreSQL中的数据类型没有相等运算符的原因。json

如果您对文本表示相等(从示例中看起来)感到满意,您可以UNION ALL使用一text列并json稍后转换:

SELECT json_col::json
FROM (
   (SELECT '{"billingcode" : "' || billingcode || '"}'::text AS json_col
    FROM   billing_2012_08 LIMIT 10)
   UNION ALL
   (SELECT '{"charged" : "' || charged || '"}'::text
    FROM   sending_response_2012_08 LIMIT 10)
   ) sub

或者您可以jsonb在 Postgres 9.4 或更高版本中使用,它带有以前缺少的相等运算符(以及其他内容)。看:

然后考虑这个替代查询:

SELECT to_jsonb(t) AS jsonb_col
FROM  (SELECT billingcode FROM billing_2012_08 LIMIT 10) t

UNION
SELECT to_jsonb(t)   -- also preserves possible numeric type!
FROM  (SELECT charged FROM sending_response_2012_08 LIMIT 10) t

ORDER  BY 1;  -- possible with jsonb

除了UNION,ORDER BY现在也是可能的。

注意使用to_jsonb(). 通过喂它一行,列名自动用作键名。这更干净、更快,并且(除其他外)保留了可能影响相等和排序顺序的可能的数字类型。(to_json()也可用。)

db<>fiddle here
sqlfiddle

于 2013-09-16T22:15:41.693 回答