我有以下输入:
name | count | options
-----------------------
user1 | 3 | ['option1', 'option2']
user1 | 12 | ['option2', 'option3']
user2 | 2 | ['option1', 'option3']
user2 | 1 | []
我想要以下输出:
name | count | options
-----------------------
user1 | 12 | ['option1', 'option2', 'option3']
user2 | 2 | ['option1', 'option3']
我按姓名分组。对于每个组,计数应汇总为max
,选项应汇总为union
。我很难弄清楚后者是怎么做的。
目前,我有这个问题:
with data(name, count, options) as (
select 'user1', 12, array['option1', 'option2']::text[]
union all
select 'user1', 12, array['option2', 'option3']::text[]
union all
select 'user2', 2, array['option1', 'option3']::text[]
union all
select 'user2', 1, array[]::text[]
)
select name, max(count)
from data
group by name
我知道这可以通过定义自定义聚合函数轻松完成,但我想通过查询来完成此操作。我理解unnest()
数组的基础知识(以及稍后的array_agg()
结果),但无法弄清楚如何在我的查询中注入它。
答案 0 :(得分:3)
您可以在unnest(options)
列表中使用FROM
使用隐式横向联接,然后使用array_agg(distinct v)
创建包含以下选项的数组:
with data(name, count, options) as (
select 'user1', 12, array['option1', 'option2']::text[]
union all
select 'user1', 12, array['option2', 'option3']::text[]
union all
select 'user2', 2, array['option1', 'option3']::text[]
union all
select 'user2', 1, array[]::text[]
)
select name, array_agg(distinct v) -- the 'v' here refers to the 'f(v)' alias below
from data, unnest(options) f(v)
group by name;
┌───────┬───────────────────────────┐
│ name │ array_agg │
├───────┼───────────────────────────┤
│ user1 │ {option1,option2,option3} │
│ user2 │ {option1,option3} │
└───────┴───────────────────────────┘
(2 rows)
答案 1 :(得分:0)
如果您无法执行嵌套操作(例如,因为您需要汇总其他列),则此函数经过了经过严格测试的汇总函数,可以连接每个单独的数组:
CREATE OR REPLACE FUNCTION concat_array_agg_sfunc(state ANYARRAY, v ANYARRAY)
RETURNS ANYARRAY AS
$$
SELECT array_cat(state, v);
$$ LANGUAGE SQL IMMUTABLE;
DROP AGGREGATE IF EXISTS concat_array_agg( ANYARRAY );
CREATE AGGREGATE concat_array_agg( ANYARRAY ) (
SFUNC = concat_array_agg_sfunc,
STYPE = ANYARRAY
);
SELECT
k,
concat_array_agg(v)
FROM (VALUES ('a', ARRAY [1,2,3]),
('a', ARRAY [4,5,6]),
('b', ARRAY [1,2,3]),
('b', ARRAY [2,3,4]),
('c', ARRAY [2,3,4]),
('c', NULL)) t(k, v)
GROUP BY k