Postgres - 加入数组值

时间:2017-10-23 14:29:55

标签: postgresql join

假设我有一个包含模式的表,如下所示

id  |  name  |   tags   |
1   |  xyz   |  [4, 5]  |

其中tags是另一个名为tags的表中对id的引用数组。

是否可以将这些标签加入到行中?即用标签表中的thise行的值替换id号,例如:

id  |  name  |                        tags                        |
1   |  xyz   | [[tag_name, description], [tag_name, description]] |

如果没有,我想知道这是架构设计的问题吗?

2 个答案:

答案 0 :(得分:2)

示例tags表:

create table tags(id int primary key, name text, description text);
insert into tags values
(4, 'tag_name_4', 'tag_description_4'),
(5, 'tag_name_5', 'tag_description_5');

您应该删除列tags,使用其元素加入表tags并聚合最后一个表的列。您可以将数组聚合到数组:

select t.id, t.name, array_agg(array[g.name, g.description])
from my_table as t
cross join unnest(tags) as tag
join tags g on g.id = tag
group by t.id;

 id | name |                            array_agg                            
----+------+-----------------------------------------------------------------
  1 | xyz  | {{tag_name_4,tag_description_4},{tag_name_5,tag_description_5}}
(1 row) 

或字符串到数组:

select t.id, t.name, array_agg(concat_ws(', ', g.name, g.description))
...

或字符串中的字符串:

select t.id, t.name, string_agg(concat_ws(', ', g.name, g.description), '; ')
...

答案 1 :(得分:2)

不确定这是否仍然对任何人都有用,但是取消标记的嵌套比让postgres直接从数组进行工作要慢得多。您可以重写查询,这样通常会提高性能,因为g.id = ANY(tags)是简单的pkey索引扫描,无需扩展步骤:

SELECT t.id, t.name, ARRAY_AGG(ARRAY[g.name, g.description])
  FROM my_table AS t
    LEFT JOIN tags AS g 
      ON g.id = ANY(tags)
  GROUP BY t.id;