需要的结果集如下表所示

时间:2015-11-30 12:08:01

标签: sql json postgresql

-- some test tables to start out with:

create table general (
    id serial primary key,
    sno smallint not null,
    name varchar not null,
    qty decimal(12,3) not null );

insert into general 
  (sno,name,qty) 
values
  (1,'a',3),
  (1,'b',4),
  (1,'c',5), 
  (2,'aa',33),
  (2,'bb',44),
  (2,'cc',55);

结果应采用以下格式

{"1",{"1":{"name":"a","qty":"3"},"2":{"name":"b","qty":"4"},"3":{"name":"c","qty":"5"}}
"2",{"1":{"name":"aa","qty":"33"},"2":{"name":"bb","qty":"44"},"3":{"name":"cc","qty":"55"}}}

1 个答案:

答案 0 :(得分:0)

首先,使用横向子查询中的to_json()来获取(name, qty)对作为json 并添加row_number()对其进行编号:

select 
    sno, to_json(t) name_qty,
    row_number() over (partition by sno) rn
from 
    general, 
    lateral (select name, qty) t;

 sno |          name_qty          | rn 
-----+----------------------------+----
   1 | {"name":"a","qty":3.000}   |  1
   1 | {"name":"b","qty":4.000}   |  2
   1 | {"name":"c","qty":5.000}   |  3
   2 | {"name":"aa","qty":33.000} |  1
   2 | {"name":"bb","qty":44.000} |  2
   2 | {"name":"cc","qty":55.000} |  3
(6 rows)

使用此(虚拟)结果两次使用json_object_agg()来汇总两个级别的数据:

select json_object_agg(sno, sno_item)
from (
    select sno, json_object_agg(rn, name_qty) sno_item
    from (
        select 
            sno, to_json(t) name_qty,
            row_number() over (partition by sno) rn
        from 
            general, 
            lateral (select name, qty) t
        ) s
    group by sno
    ) s;

Postgres 9.5 中,您可以使用jsonb_pretty()获取可读结果:

select jsonb_pretty(json_object_agg(sno, sno_item)::jsonb)
from (
    select sno, json_object_agg(rn, name_qty) sno_item
    from (
        select 
            sno, to_json(t) name_qty,
            row_number() over (partition by sno) rn
        from 
            general, 
            lateral (select name, qty) t
        ) s
    group by sno
    ) s;

        jsonb_pretty        
----------------------------
 {                         +
     "1": {                +
         "1": {            +
             "qty": 3.000, +
             "name": "a"   +
         },                +
         "2": {            +
             "qty": 4.000, +
             "name": "b"   +
         },                +
         "3": {            +
             "qty": 5.000, +
             "name": "c"   +
         }                 +
     },                    +
     "2": {                +
         "1": {            +
             "qty": 33.000,+
             "name": "aa"  +
         },                +
         "2": {            +
             "qty": 44.000,+
             "name": "bb"  +
         },                +
         "3": {            +
             "qty": 55.000,+
             "name": "cc"  +
         }                 +
     }                     +
 }
(1 row)