简体   繁体   English

如何通过重叠 jsonb 值来连接表? (PostgreSQL)

[英]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?要连接venuessports ,以便连接的表至少有一个共同元素,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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM