我有下表
MyTable
:
id │ value_two │ value_three │ value_four
────┼───────────┼─────────────┼────────────
1 │ a │ A │ AA
2 │ a │ A2 │ AA2
3 │ b │ A3 │ AA3
4 │ a │ A4 │ AA4
5 │ b │ A5 │ AA5
我想查询按
{ value_three, value_four }
分组的对象数组value_two
。 value_two
应该单独出现在结果中。结果应该是这样的:
value_two │ value_four
───────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
a │ [{"value_three":"A","value_four":"AA"}, {"value_three":"A2","value_four":"AA2"}, {"value_three":"A4","value_four":"AA4"}]
b │ [{"value_three":"A3","value_four":"AA3"}, {"value_three":"A5","value_four":"AA5"}]
不管是用
json_agg()
还是array_agg()
.
然而我能做的最好的是:
with MyCTE as ( select value_two, value_three, value_four from MyTable )
select value_two, json_agg(row_to_json(MyCTE)) value_four
from MyCTE
group by value_two;
哪个返回:
value_two │ value_four
───────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
a │ [{"value_two":"a","value_three":"A","value_four":"AA"}, {"value_two":"a","value_three":"A2","value_four":"AA2"}, {"value_two":"a","value_three":"A4","value_four":"AA4"}]
b │ [{"value_two":"b","value_three":"A3","value_four":"AA3"}, {"value_two":"b","value_three":"A5","value_four":"AA5"}]
在对象中有一个额外的
value_two
键,我想摆脱它。我应该使用哪个 SQL (Postgres) 查询?
json_build_object()
在 Postgres 9.4 或更新版本中jsonb_build_object()
返回jsonb
.
SELECT value_two, json_agg(json_build_object('value_three', value_three
, 'value_four' , value_four)) AS value_four
FROM mytable
GROUP BY value_two;
从可变参数列表中构建一个 JSON 对象。按照惯例, 参数列表由交替的键和值组成。
row_to_json()
带有 ROW
表达式就可以了:
SELECT value_two
, json_agg(row_to_json((value_three, value_four))) AS value_four
FROM mytable
GROUP BY value_two;
但是你失去了原来的列名。转换为已注册的行类型可以避免这种情况。 (临时表的行类型也适用于即席查询。)
CREATE TYPE foo AS (value_three text, value_four text); -- once in the same session
SELECT value_two
, json_agg(row_to_json((value_three, value_four)::foo)) AS value_four
FROM mytable
GROUP BY value_two;
或者使用 subselect 而不是
ROW
表达式。更冗长,但没有类型转换:
SELECT value_two
, json_agg(row_to_json((SELECT t FROM (SELECT value_three, value_four) t))) AS value_four
FROM mytable
GROUP BY value_two;
Craig 相关回答中的更多解释:
to_json 与 array_agg 与 复合类型
begin;
create table mytable(
id bigint, value_two text, value_three text, value_four text);
insert into mytable(id,value_two, value_three,value_four)
values
( 1, 'a', 'A', 'AA'),
(2, 'a' , 'A2' , 'AA2'),
(3, 'b' , 'A3', 'AA3'),
( 4, 'a' , 'A4', 'AA4'),
(5, 'b' , 'A5', 'AA5');
commit;
create type mytable_type as (value_three text, value_four text);
select value_two,
to_json( array_agg(row(value_three,value_four)::mytable_type))
from mytable
group by 1;
使用
jsonb_agg
和to_jsonb
。
SELECT
value_two,
jsonb_agg(to_jsonb (t.*) - '{id,value_two}'::text[]) AS data
FROM
mytable t
GROUP BY
1
ORDER BY
1;
基于手册参考
jsonb - 文本 [] → jsonb
从左操作数中删除所有匹配的键或数组元素。