将多行与JSOB合并为一行

时间:2016-05-10 04:52:09

标签: postgresql

我有一些看起来像这样的行:

"id","name","data","created_at"
110,"customerAdd","{\"age\": \"23\", \"name\": \"sally\", \"status\": \"valid\"}","2016-05-10 00:18:53.325752"
111,"customerUpdate","{\"age\": \"19\", \"name\": \"sally\"}","2016-05-10 00:18:53.331443"
112,"customerDelete","{\"name\": \"sally\", \"status\": \"deleted\"}","2016-05-10 00:18:53.338929"

使用这样的查询:

SELECT * FROM events WHERE data->>'name' = 'sally';

我正在寻找一种方法来将所有这些行压扁/缩小/连接成一行。

使用JSON,就像这样:

{'age': 19, 'status': 'deleted', name: 'sally'}

或者在实际的列中,如下所示:

age, status, name
19, deleted, sally

一般的想法是,我想将每个道具解析为它所分配的最后一个值,但我希望这种情况发生得很深。

我正在寻找任何入门方式。

1 个答案:

答案 0 :(得分:0)

您可以对来自jsonb_each_text的键和值使用DISTINCT,按created_at desc排序,然后使用jsonb_object重新组合所有值:

with
  events(id,name,data,created_at) as (
    values (110,'customerAdd','{"age": "23", "name": "sally", "status": "valid"}'::jsonb,'2016-05-10 00:18:53.325752'::timestamp),
           (111,'customerUpdate','{"age": "19", "name": "sally"}','2016-05-10 00:18:53.331443'),
           (112,'customerDelete','{"name": "sally", "status": "deleted"}','2016-05-10 00:18:53.338929')
    ),
  flattened as (
    select distinct on (kv.key) *
    from events e
    join lateral jsonb_each_text(data) kv on true
    order by kv.key, e.created_at desc
    )

select jsonb_object(array(select key   from flattened order by key),
                    array(select value from flattened order by key))