在postgres 9.6中,我有一个包含这3列的表格。
id | val1 | val2
------------------
1 | x | 1
1 | x | 2
1 | x | 3
1 | y | 4
2 | y | 1
2 | y | 2
我可以使用聚合函数将其转换为此吗?
id |
------------------------------
1 | { x: [1, 2, 3], y: [4] }
2 | { y: [1, 2] }
或者如果我无法找到我想要的东西,下面的东西也可以。或者任何允许我在我的应用程序代码中将结果转换为上述内容的东西。
id |
------------------------------
1 | [ {x: 1}, {x: 2}, {x: 3}, {y: 4} ]
2 | [ {y: 1}, {y: 2} ]
我知道我可以执行select id, array_agg(val2) from mytable group by val2
之类的操作,但只能按val2
分组并返回类似
id |
------------------
1 | [1, 2, 3, 4]
2 | [1, 2]
答案 0 :(得分:5)
以下是使用jsonb_agg and jsonb_object_agg functions
的一种方法with the_table(id , val1 , val2) as(
select 1 ,'x',1 union all
select 1 ,'x', 2 union all
select 1 ,'x', 3 union all
select 1 ,'y', 4 union all
select 2 ,'y', 1 union all
select 2 ,'y', 2
)
select id, jsonb_object_agg(val1, arr) from (
select id, val1, jsonb_agg(val2) as arr
from the_table
group by id, val1
)t
group by id
答案 1 :(得分:5)
你可以用:
SELECT
id, json_object_agg(val1, aaa)
FROM
(
SELECT
id, val1, json_agg(val2) AS aaa
FROM
t
GROUP BY
id, val1
) AS q
GROUP BY
id;
id | json_object_agg -: | :----------------------------- 1 | { "x" : [1, 2, 3], "y" : [4] } 2 | { "y" : [1, 2] }
您可以在 dbfiddle here
找到生成此结果所需的定义您将使用这两个功能:
可以在PostgreSQL doc
中的9.20. Aggregate Functions找到该文档答案 2 :(得分:1)
另一个有用的代码片段受到SO问题的启发:
drop aggregate if exists jsonb_objarr_agg(text, anyelement);
drop function if exists jsonb_objarr_agg_func(jsonb, text, anyelement);
create function jsonb_objarr_agg_func(jsonb, text, anyelement) returns jsonb immutable language sql as $$
select
jsonb_set(
$1,
array[$2],
coalesce(
case
when jsonb_typeof($1->$2) <> 'array' then to_jsonb(array[$1->$2])
else $1->$2
end,
'[]'::jsonb) || to_jsonb($3), true);
$$;
select jsonb_objarr_agg_func('{"a":1}', 'a', 2);
create aggregate jsonb_objarr_agg(text, anyelement) (
sfunc = jsonb_objarr_agg_func,
stype = jsonb,
initcond = '{}');
with t(i, v1, v2) as (values
(1, 'x', 1),
(1, 'x', 2),
(1, 'x', 3),
(1, 'y', 4),
(2, 'y', 1),
(2, 'y', 2))
select
i,
jsonb_objarr_agg(v1, v2)
from t
group by i;
╔═══╤════════════════════════════╗ ║ i │ jsonb_objarr_agg ║ ╠═══╪════════════════════════════╣ ║ 1 │ {"x": [1, 2, 3], "y": [4]} ║ ║ 2 │ {"y": [1, 2]} ║ ╚═══╧════════════════════════════╝
此聚合允许使用第一个参数作为键jsonb
,并将第二个参数聚合到数组中。
如果您需要json
类型,则可以在此代码中轻松将jsonb
替换为json
。
答案 3 :(得分:0)
我认为以下是您想要的:
select id, json_agg(json_build_object(val1, val2s ))
from (select id, val1, array_agg(val2) as val2s
from t
group by id, val1
) t
group by id;