【问题标题】:How to write postgresql query to build the json output like this?如何编写 postgresql 查询来构建这样的 json 输出?
【发布时间】:2020-07-20 22:56:51
【问题描述】:

我有一个包含 2 级分层数据的 postgresql 有理表,我想编写一个查询来构建如下所示的 json 输出,我尝试了一段时间但无法弄清楚。我想需要使用一些函数,如 row_to_json、json_agg、json_build_object、json_build_array 等,但我真的无法成功完成。 任何人都可以提供帮助,谢谢!

将此有理表作为输入:

select * from team;
+------------+------------+------------+
| country    | city       | member     |
|------------+------------+------------|
| china      | bejing     | betty      |
| china      | bejing     | bruce      |
| china      | shanghai   | scott      |
| usa        | chicago    | cindy      |
| usa        | newyork    | nancy      |
| usa        | newyork    | nathan     |
+------------+------------+------------+
SELECT 6

想要一个像下面这样的 json 作为输出:

[
    {
        "name": "china",
        "type": "country",
        "children": [
            {
                "name": "beijing",
                "type": "city",
                "children": [
                    { "name": "betty", "type": "member" },
                    { "name": "bruce", "type": "member" }
                ]
            },
            {
                "name": "shanghai",
                "type": "city",
                "children": [
                    { "name": "scott", "type": "member" }
                ]
            }
        ]
    },
    {
        "name": "usa",
        "type": "country",
        "children": [
            {
                "name": "chicago",
                "type": "city",
                "children": [
                    { "name": "cindy", "type": "member" }
                ]
            },
            {
                "name": "newyork",
                "type": "city",
                "children": [
                    { "name": "nancy", "type": "member" },
                    { "name": "nathan", "type": "member" }
                ]
            }
        ]
    }
]

【问题讨论】:

    标签: json postgresql hierarchical


    【解决方案1】:

    我可能会写

    SELECT json_agg(json_build_object(
       'type', 'country',
       'name', country,
       'children', children
    )) AS root
    FROM (
       SELECT country, json_agg(json_build_object(
           'type', 'city',
           'name', city,
           'children', children
       )) AS children
       FROM (
           SELECT country, city, json_agg(json_build_object(
               'type', 'member',
               'name', member
           )) as children
           FROM team
           GROUP BY country, city
       ) cities
       GROUP BY country
    ) countries
    

    (online demo)

    不幸的是,我没有找到在json_build_object 中使用子查询编写此内容的方法。

    【讨论】:

    • 太棒了,伯吉!!!逻辑很清晰,非常感谢!祝你有美好的一天!
    【解决方案2】:

    以下是我对表结构的建议:

    with team (country, city, member) as (
        values 
            ('china', 'bejing', 'betty'),
            ('china', 'bejing', 'bruce'),
            ('china', 'shanghai', 'scott'),
            ('usa', 'chicago', 'cindy'),
            ('usa', 'newyork', 'nancy'),
            ('usa', 'newyork', 'nathan')
    ) -- the real code is after this line
    select jsonb_pretty(json_agg(json_build_object('name', c.country, 'type', 'country', 'children', ct.children) order by c.country)::jsonb)
    from (select country from team group by country) c
    left join (
        select ct.country, json_agg(json_build_object('name', ct.city, 'type', 'city', 'children', m.children) order by ct.city) as children
        from (select country, city from team group by country, city) ct
        left join (
            select country, city, json_agg(json_build_object('name', member, 'type', 'member') order by member) as children
            from team
            group by country, city
        ) m on ct.country = m.country and ct.city = m.city
        group by ct.country
    ) ct on c.country = ct.country;
    

    【讨论】:

    • 谢谢Karianpour,你的回答也很清楚,非常感谢!祝你有美好的一天!
    猜你喜欢
    • 2021-06-05
    • 1970-01-01
    • 1970-01-01
    • 2020-01-10
    • 1970-01-01
    • 2019-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多