【问题标题】:Return as array of JSON objects in SQL (Postgres)在 SQL (Postgres) 中作为 JSON 对象数组返回
【发布时间】:2014-12-16 16:23:26
【问题描述】:

我有下表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_two 分组的对象数组{ value_three, value_four }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) 查询?

【问题讨论】:

    标签: sql arrays json postgresql aggregate-functions


    【解决方案1】:

    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;

    The manual:

    根据可变参数列表构建 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;
    

    但是您丢失了原始列名。强制转换为已注册的行类型可以避免这种情况。 (临时表的行类型也可用于临时查询。)

    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;

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

    db小提琴here
    sqlfiddle

    【讨论】:

    • 谢谢,但这会返回带有自动生成密钥的对象:{"f1":"a","f2":"AA"}。如何将f1 重命名为value_three
    • @ehmicky:是的,如果您也想要列名,则需要将行转换为众所周知的复合类型。我再补充一点。
    • 子选择,甚至 OP 的 cte 可能是为行的列名起别名的更方便的方法。 stackoverflow.com/questions/13227142/…
    • 作为样式说明,我认为当我们将更新放在答案顶部并在原始注释下方注明它们适用的版本时,对于新人来说会更容易。只要您保持答案,它就永远是好的,随着时间的推移,对旧 PostgreSQL 的建议变得不那么有用了。
    • @Evan:我同意。我懒得更新我所有的旧答案。但既然这个无论如何都需要更新......
    猜你喜欢
    • 2019-01-27
    • 1970-01-01
    • 1970-01-01
    • 2017-01-20
    • 1970-01-01
    • 2019-12-09
    • 1970-01-01
    • 1970-01-01
    • 2020-10-13
    相关资源
    最近更新 更多