You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL如何按相同id聚合行 合并对应年份数组值

PostgreSQL按分组合并各列非空数组实现方法

场景说明

现有表存储按用户、年份标记的标签数组,同一id+name的标签散落在多行,每行仅存储单个年份的非空标签值,需要按id、name分组后,将各年份的非空标签聚合为单行记录。
样例源数据:

id  name  2019           2020        2021
1   Ana   {fruit,health}      
1   Ana                             {veggie}
2   Bill  {beauty}
2   Bill                 {veggie}
2   Bill                            {health,veggie}

期望输出:

id  name  2019            2020        2021
1   Ana   {fruit, health}           {veggie}
2   Bill  {beauty}        {veggie}    {health,veggie}

实现方案

方案1:适用于样例场景(同组同年份列最多1个非空值)

样例数据中每个分组下每个年份列最多只有1条非空记录,直接使用max()聚合即可自动跳过null值,拿到唯一的有效数组,写法最简单、执行效率最高:

-- 假设表名为 user_tag
SELECT
  id,
  name,
  max("2019") AS "2019",
  max("2020") AS "2020",
  max("2021") AS "2021"
FROM user_tag
GROUP BY id, name
ORDER BY id;

说明:PostgreSQL支持数组类型的大小比较,聚合时null会被直接忽略,因此同组下该列唯一的非空数组会被max()正确取出。

方案2:通用场景(同组同年份列存在多个非空值,需合并去重)

如果业务中存在同个分组下同一年份有多条非空标签数组,需要把数组合并、标签去重的场景,可以使用数组聚合+展开去重的写法:

SELECT
  id,
  name,
  -- 聚合2019年所有标签,去重后生成数组
  array(SELECT DISTINCT unnest(array_accum("2019"))) AS "2019",
  array(SELECT DISTINCT unnest(array_accum("2020"))) AS "2020",
  array(SELECT DISTINCT unnest(array_accum("2021"))) AS "2021"
FROM user_tag
GROUP BY id, name
ORDER BY id;

说明:array_accum是PostgreSQL内置的聚合函数,会将同组下所有输入的数组合并为一个大数组、自动跳过空值;unnest将大数组拆分为单个标签元素,DISTINCT去重后再通过array()构造器重新组装为最终的标签数组。

内容的提问来源于stack exchange,提问作者Joehat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 01:21:34