我在我的数据库中使用 PostgreSQL JSON 类型字段。
JSON格式:
[
{"id": "13", "something": "not_important"},
{"id": "5426565165191919", "something": "not_important"},
{"id": "46", "something": "not_important"}
...
]
["13", "46", "84"]
等ID列表。
如何进行查询,告诉我某些ID不存在? (哪一个不重要。)
答案 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;
WITH
查询)只是替换实际的表t
。LEFT JOIN / NOT NULL
识别缺失值。细节:
bigint
的宽度足以容纳id
值。否则,请切换到numeric
。在这个相关答案中有更多解释:
答案 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
文本直接转换为整数值,例如如int
或bigint
,即使整个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