Как написать запрос postgresql для создания вывода json, как это? - PullRequest
0 голосов
/ 08 апреля 2020

У меня есть рациональная таблица postgresql, которая имеет двухуровневые иерархические данные, и я хочу написать запрос для построения вывода json, как показано ниже, я пытался некоторое время, но не могу понять. Я думаю, нужно использовать некоторые функции, такие как row_to_ json, json_agg, json_build_object, json_build_array и др. c. но я действительно не могу сделать это успешно. Любой может помочь, спасибо!

Иметь эту рациональную таблицу в качестве ввода:

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" }
                ]
            }
        ]
    }
]

Ответы [ 2 ]

0 голосов
/ 08 апреля 2020

Я бы, вероятно, написал

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

( онлайн-демонстрация )

К сожалению, я не нашел способа написать это с подзапросами в json_build_object .

0 голосов
/ 08 апреля 2020

Вот что я предлагаю относительно структуры таблицы:

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;
...