Sql JSON字段检查查询中存在

Sql JSON字段检查查询中存在,sql,arrays,json,postgresql,exists,Sql,Arrays,Json,Postgresql,Exists,我正在数据库中使用PostgreSQL JSON类型字段 JSON格式: [ {"id": "13", "something": "not_important"}, {"id": "5426565165191919", "something": "not_important"}, {"id": "46", "something": "not_important"} ... ] ID列表,如[“13”、“46”、“84”] 如何进行查询,告诉我某个ID不存在?(哪一个不重

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

JSON格式:

[
   {"id": "13", "something": "not_important"},
   {"id": "5426565165191919", "something": "not_important"},
   {"id": "46", "something": "not_important"}
   ...
]
ID列表,如
[“13”、“46”、“84”]

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

  • CTE(
    WITH
    query)只是替换实际的表
    t
  • 使用
    LEFT JOIN/NOT NULL
    识别缺少的值。细节:
  • 假设
    bigint
    足够宽,可以容纳
    id
    值。否则,请切换到
    数值

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


您可以通过左键将“预期”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\u array\u elements()
从每个json字符串中提取单个数组元素。因为目标JSON字符串有对象数组元素,所以我们必须进一步提取
“id”
值,这可以通过
->
操作符完成。请注意,
value
似乎是
json\u array\u elements()
函数为单列输出指定的默认名称

一个怪癖是,提取的JSON(即
值)仍然是
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
这就是为什么我必须用
::varchar::bigint
强制转换
json

此外,我还必须使用
substring()
,从双引号字符串中提取预期的ID,否则
::bigint
强制转换将无法工作

还有一点,我使用了
bigint
而不是
int
,因为这里有一个相当大的数字(54265651651919)

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

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

您可以通过使用(返回
文本
)而不是
->
,来避免额外的强制转换。啊,这一点很好。有没有办法避免在预期的ids子查询中进行额外的强制转换?这里没有解引用,它只是
value::varchar
,因此不能使用
->
。您可以使用
json\u array\u elements()
的另一个实例,只要将输入作为json数组提供即可。我在回答中使用了一个普通数组(
bigint[]
)和相应的
unnest()
),它很有效!谢谢你。
select
    case when count(expected.id)>0 then true else false end some_missing