我有下表,我想要布局名称为userid ='user-1'和gridname ='RT'的
| userid | defaultdata |
|--------|------------------------------------------------------------------------------------------|
| user-1 | [{"gridname":"RT", "layoutname":"layout-1"},{"gridname":"RT2", "layoutname":"layout-2"}] |
| user-2 | [{"gridname":"RT", "layoutname":"layout-3"},{"gridname":"RT2", "layoutname":"layout-2"}] |
到目前为止,我已经尝试过了。
SELECT userid, obj.value->>'gridname' AS gridname
FROM col.userdefault t
JOIN lateral jsonb_array_elements(t.defaultdata::jsonb) obj(value) ON
obj.value->>'_gridname' = 'RT'
WHERE defaultdata @> '[{"_gridname":"RT"}]';
但无法正常工作并出现以下错误:
ERROR: operator does not exist: json @> unknown
LINE 4: WHERE defaultdata @> '[{"_gridname":"RT"}]::jsonb';
^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
SQL state: 42883
Character: 198
答案 0 :(得分:3)
要获取gridname的值,您必须扩展数组,然后检查其每个元素:
SELECT
userid,
elems ->> 'layoutname' AS layoutname -- 3
FROM
mytable,
json_array_elements(defaultdata) elems -- 1
WHERE userid = 'user-1' AND elems ->> 'gridname' = 'RT' -- 2
我和@>
比较器一起玩。我发现您的方法还不错(假设您将使用jsonb
类型而不是json
类型)。 @>
可以完成工作:
SELECT
*
FROM mytable
WHERE defaultdata @> '[{"gridname":"RT"}]'
这将返回整个数组,而不仅是包含此数组的元素。这意味着如果您以这种方式使用它,它将返回其中任何元素包含此部分的数组。
要获得一个元素,您需要将其扩展为已经完成的工作。唯一的问题是您没有在WHERE子句中使用扩展元素,而是使用原始数据。使用扩展的元素将导致以下查询:
SELECT
userid,
elems ->> 'layoutname' AS layoutname
FROM mytable,
jsonb_array_elements(defaultdata) elems
WHERE userid = 'user-1' AND elems @> '{"gridname":"RT"}'
这很好!
答案 1 :(得分:3)
@>
不存在json
运算符,仅jsonb
不存在。
您可以使用显式类型转换来消除即时错误,如错误消息所示:
WHERE defaultdata::jsonb @> '...'
再往前看,我想知道json
是否是适合您的数据类型。对于要在数据库内部有效处理的数据,jsonb
更好。