[英]How to join tables by overlapping jsonb values? (PostgreSQL)
To clarify the question, here's an example:为了澄清这个问题,这里有一个例子:
Table venues
id match_ids (jsonb)
---------------------
1 []
2 [112]
3 ["25", 112]
4 [25, 112]
5 ["112"]
6 ["999"]
Table sports
id object (jsonb)
--------------------
1 {"match_ids": [25, 112]}
2 {}
3
To join venues
and sports
so that the joined table has at least one element in common, how does the SQL statement have to look like?要连接
venues
和sports
,以便连接的表至少有一个共同元素,SQL 语句必须是什么样子?
Here's the expected outcome:这是预期的结果:
sports.id venue.id venue.match_ids
-------------------------------
1 2 [112]
1 3 ["25", 112]
1 4 [25, 112]
1 5 ["112"]
I wrote the following...我写了以下...
select * from venues
join sports on venues.match_ids <@ sports.object::jsonb->'match_ids';
... but this resulted in ...但这导致
ERROR: operator does not exist: boolean -> unknown
LINE 4: sports.object::jsonb->'match_ids';
^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
(Here's a fiddle: https://dbfiddle.uk/?rdbms=postgres_13&fiddle=d5263069f490828288c30b6a51a181c8 ) (这是一个小提琴: https://dbfiddle.uk/?rdbms=postgres_13&fiddle=d5263069f490828288c30b6a51a181c8 )
Any advice will be appreciated!任何建议将被认真考虑!
PS: I use PostgreSQL v13. PS:我使用 PostgreSQL v13。
I managed to solve the issue by moving from jsonb
to array and working with array intersect &&
我设法通过从
jsonb
移动到 array 并使用 array intersect &&
来解决这个问题
select * from venues
join sports on ARRAY(SELECT jsonb_array_elements(match_ids)::varchar)
&&
ARRAY(SELECT jsonb_array_elements(sports.object::jsonb->'match_ids')::varchar);
https://dbfiddle.uk/?rdbms=postgres_13&fiddle=5143f236235e4411c729f41a60c69012 https://dbfiddle.uk/?rdbms=postgres_13&fiddle=5143f236235e4411c729f41a60c69012
EDIT from the original poster从原始海报编辑
Thank you so much @Ftisiot for this brilliant solution.非常感谢@Ftisiot 这个出色的解决方案。 However, I found that this approach works if
match_ids
in venues
has integers only.但是,我发现如果
venues
中的match_ids
仅具有整数,则此方法有效。 If the column has texts, it may not work.如果该列有文本,它可能不起作用。 To select both texts and integers,
jsonb_array_elements_text
should be used.对于 select 文本和整数,应使用
jsonb_array_elements_text
。
eg例如
select * from venues
join sports on ARRAY(SELECT jsonb_array_elements_text(match_ids))
&&
ARRAY(SELECT jsonb_array_elements_text(sports.object::jsonb->'match_ids'));
https://dbfiddle.uk/?rdbms=postgres_13&fiddle=64f8fac38ccf73d38834c22e90ba4b2c https://dbfiddle.uk/?rdbms=postgres_13&fiddle=64f8fac38ccf73d38834c22e90ba4b2c
Change the precedence with parentheses:用括号改变优先级:
... on venues.match_ids <@ (sports.object::jsonb->'match_ids')
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.