在SQL中返回JSON对象数组(Postgres)

ehm*_*cky 19 sql arrays postgresql json aggregate-functions

我有下表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
Run Code Online (Sandbox Code Playgroud)

我想查询{ 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"}]
Run Code Online (Sandbox Code Playgroud)

它是否使用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;
Run Code Online (Sandbox Code Playgroud)

哪个回报:

 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"}]
Run Code Online (Sandbox Code Playgroud)

value_two在对象中有一个额外的键,我想摆脱它.我应该使用哪个SQL(Postgres)查询?

Erw*_*ter 50

json_build_object() 在Postgres 9.4或更新版本中

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;
Run Code Online (Sandbox Code Playgroud)

手册:

从可变参数列表构建JSON对象.按照惯例,参数列表由交替的键和值组成.

任何版本(包括Postgres 9.3)

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;
Run Code Online (Sandbox Code Playgroud)

但是你松散了原始的列名.对已注册的行类型进行强制转换可避免这种情况.(临时表的行类型也用于即席查询.)

CREATE TYPE foo AS (value_three text, value_four text);  -- once in the same session
Run Code Online (Sandbox Code Playgroud)
SELECT value_two
     , json_agg(row_to_json((value_three, value_four)::foo)) AS value_four
FROM   mytable
GROUP  BY value_two;
Run Code Online (Sandbox Code Playgroud)

或者使用子选择而不是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;
Run Code Online (Sandbox Code Playgroud)

克雷格的相关答案中有更多解释:

db <> 在这里摆弄
老SQL小提琴.

  • 作为样式说明,我认为当我们将更新放在答案顶部并将原始注释放在其下方并附上有关它们适用于哪个版本的注释时,对新手来说会更容易。只要您保持答案,它就永远是好的,并且随着时间的推移,针对较旧 PostgreSQL 的建议变得不那么有用了。 (2认同)