有没有办法通过其值查找 jsonb 列
Is there a way to lookup a jsonb column by its values
我在 postgres 12 中有一个 table、test
,带有一个 jsonb 列,data_col
,它有许多不同的键和值。
我的要求是 select * 从那个 table 那里值匹配一个字符串。
例如table有如下数据
id some_value data_col
---------------------------------------------------------------
11 2018 {"a": "Old Farm"}
12 2019 {"b": "My house is old", "c": "See you tomorrow"}
13 2020 {"d": "The old house", "a": "Very Green", "e": "Olden days"}
如您所见,有许多不同的键,因此像网络上的示例建议的那样查找是不切实际的,即 col_name->>'Key'
我想写一个带有 where 子句的 sql,以便为我提供其中包含字符串“old”的所有行。
类似于:
select * from test where data_col ILIKE '%old%'
应该给我
11, 2018, Old Farm
12, 2019, My house is old
13, 2020, Olden days
一个选项使用 jsonb_each()
:
select t.*, x.*
from test t
cross join lateral jsonb_each(t.data_col) x
where x.value ilike '%old%'
请注意,如果一个对象不止一次包含“old”,这会增加行数。为避免这种情况,您可以使用 exists
代替:
select t.*
from test t
where exists (
select 1
from jsonb_each(t.data_col) x
where x.val ilike '%old%'
)
或者,如果您想将所有匹配值汇总到一列中:
select t.*, x.*
from test t
cross join lateral (
select string_agg(x.val, ',') as vals
from jsonb_each(t.data_col) x
where x.val ilike '%old%'
) x
where x.vals is not null
由于您使用的是 Postgres 12,因此您可以使用 SQL/JSON 路径函数:
select id, some_value,
jsonb_path_query_first(data_col, '$.* ? (@ like_regex "old" flag "i")') #>> '{}'
from data
#>>
运算符仅用于将标量 JSON 值转换为文本(因为没有从 jsonb
到 text
的直接转换会删除双引号)
如果子字符串可能有更多值,您可以使用 jsonb_path_query_array()
将它们作为一个数组(显然您需要删除 #>>
然后)
我在 postgres 12 中有一个 table、test
,带有一个 jsonb 列,data_col
,它有许多不同的键和值。
我的要求是 select * 从那个 table 那里值匹配一个字符串。
例如table有如下数据
id some_value data_col
---------------------------------------------------------------
11 2018 {"a": "Old Farm"}
12 2019 {"b": "My house is old", "c": "See you tomorrow"}
13 2020 {"d": "The old house", "a": "Very Green", "e": "Olden days"}
如您所见,有许多不同的键,因此像网络上的示例建议的那样查找是不切实际的,即 col_name->>'Key'
我想写一个带有 where 子句的 sql,以便为我提供其中包含字符串“old”的所有行。
类似于:
select * from test where data_col ILIKE '%old%'
应该给我
11, 2018, Old Farm
12, 2019, My house is old
13, 2020, Olden days
一个选项使用 jsonb_each()
:
select t.*, x.*
from test t
cross join lateral jsonb_each(t.data_col) x
where x.value ilike '%old%'
请注意,如果一个对象不止一次包含“old”,这会增加行数。为避免这种情况,您可以使用 exists
代替:
select t.*
from test t
where exists (
select 1
from jsonb_each(t.data_col) x
where x.val ilike '%old%'
)
或者,如果您想将所有匹配值汇总到一列中:
select t.*, x.*
from test t
cross join lateral (
select string_agg(x.val, ',') as vals
from jsonb_each(t.data_col) x
where x.val ilike '%old%'
) x
where x.vals is not null
由于您使用的是 Postgres 12,因此您可以使用 SQL/JSON 路径函数:
select id, some_value,
jsonb_path_query_first(data_col, '$.* ? (@ like_regex "old" flag "i")') #>> '{}'
from data
#>>
运算符仅用于将标量 JSON 值转换为文本(因为没有从 jsonb
到 text
的直接转换会删除双引号)
如果子字符串可能有更多值,您可以使用 jsonb_path_query_array()
将它们作为一个数组(显然您需要删除 #>>
然后)