JSON字段中的存在检查查询

时间:2015-01-31 18:04:15

标签: sql arrays json postgresql exists

我在我的数据库中使用 PostgreSQL JSON 类型字段。

JSON格式:

[
   {"id": "13", "something": "not_important"},
   {"id": "5426565165191919", "something": "not_important"},
   {"id": "46", "something": "not_important"}
   ...
]

["13", "46", "84"]等ID列表。

如何进行查询,告诉我某些ID不存在? (哪一个不重要。)

2 个答案:

答案 0 :(得分:2)

WITH t(data) AS (
   VALUES ('           [
   {"id": "13", "something": "not_important"},
   {"id": "5426565165191919", "something": "not_important"},
   {"id": "46", "something": "not_important"}
   ]'::json)
   )
SELECT NOT EXISTS (
   SELECT data::text, o::text  -- cast to text for display in fiddle
   FROM   t, json_array_elements(t.data) AS d(o)
   RIGHT  JOIN unnest('{13,46,84}'::bigint[]) u(id) ON u.id = (d.o->>'id')::bigint
   WHERE  d.o IS NULL
   ) AS all_found;

SQL Fiddle.

在这个相关答案中有更多解释:

答案 1 :(得分:0)

您可以通过将“预期”ID与“实际”ID相加,然后过滤“实际”ID表无法加入的结果集中的行来执行此操作。唯一的技巧是从JSON中提取整数id值。这是如何做到的,假设您正在SQL中对所有 ID进行硬编码:

select
    expected.id
from
    (select substring(value::varchar from 2 for char_length(value::varchar)-2)::bigint id from json_array_elements('["13","46","84"]'::json)) expected
    left join (select (value->>'id')::bigint id from json_array_elements('[{"id":"13"},{"id":"5426565165191919"},{"id":"46"}]'::json)) actual on actual.id=expected.id
where
    actual.id is null
;

在上面的查询中,我正在调用json_array_elements()从每个JSON字符串中提取单个数组元素。由于目标JSON字符串具有对象数组元素,因此我们必须进一步提取"id"值,这可以使用->运算符完成。请注意,value似乎是json_array_elements()函数分配给单列输出的默认名称。

一个奇怪的是,提取的JSON(即value值)仍然是json类型,并且您似乎无法将json文本直接转换为整数值,例如如intbigint,即使整个json文字仅由有效的int / bigint组成,您也可以查看varchar到达那里:

select '34'::json::bigint; -- "ERROR:  cannot cast type json to bigint"
select '34'::json::varchar::bigint; -- works, 34

这就是为什么我必须使用json转换::varchar::bigint值。

另外,我必须使用substring()从双引号字符串中提取预期的ID,因为::bigint强制转换不会起作用。

另外,小问题,我使用了bigint而不是int,因为那里有一个相当大的数字(5426565165191919)。

如果您只想选择一个布尔值,指示是否缺少至少一个预期的id,您可以将select子句更改为:

select
    case when count(expected.id)>0 then true else false end some_missing