我有一个返回包含jsonb对象的单个列的查询。以下是一些返回行的示例(此处为jsonb::text
的易读性):
[{"amount": 3, "consumable": "Mitsu 90mm ODEX Pilot Bit", "consumed_date": "2017-02-17"}]
[{"amount": 3, "consumable": "BOP Rubber", "consumed_date": "2017-02-17"}]
[{"amount": 13, "consumable": "NWJ Long Saver Sub Pin x Box", "consumed_date": "2017-02-18"},
{"amount": 70, "consumable": "NWJ Long Saver Sub Pin x Box", "consumed_date": "2017-02-17"}]
[{"amount": 63, "consumable": "Methyl Hydrate - Per Litre", "consumed_date": "2017-02-17"}]
[{"amount": 6, "consumable": "Cyclone Discharge Hose Assembly", "consumed_date": "2017-02-17"}]
给出这些示例数据,我想要一个查询来生成一个具有模式的表
consumable | 2017-02-17 | 2017-02-18
`````````````````````````````````````````````````````````
BOP Rubber | 3 | NULL
Cyclone Discharge Hose Assembly | 6 | NULL
Methyl Hydrate - Per Litre | 63 | NULL
Mitsu 90mm ODEX Pilot Bit | 3 | NULL
NWJ Long Saver Sub Pin x Box | 70 | 13
无法将tablefunc
扩展名添加到此数据库实例。
答案 0 :(得分:2)
您可以为每个consumable
在json对象中汇总金额。 jsons以consumed_dates
为键:
with test(js) as (
values
('[{"amount": 3, "consumable": "Mitsu 90mm ODEX Pilot Bit", "consumed_date": "2017-02-17"}]'::jsonb),
('[{"amount": 3, "consumable": "BOP Rubber", "consumed_date": "2017-02-17"}]'),
('[{"amount": 13, "consumable": "NWJ Long Saver Sub Pin x Box", "consumed_date": "2017-02-18"}, {"amount": 70, "consumable": "NWJ Long Saver Sub Pin x Box", "consumed_date": "2017-02-17"}]'),
('[{"amount": 63, "consumable": "Methyl Hydrate - Per Litre", "consumed_date": "2017-02-17"}]'),
('[{"amount": 6, "consumable": "Cyclone Discharge Hose Assembly", "consumed_date": "2017-02-17"}]')
)
select consumable, jsonb_object_agg(consumed_date, amount) as amounts
from (
select
e->>'consumable' as consumable,
(e->>'amount')::int as amount,
e->>'consumed_date' as consumed_date
from test,
lateral jsonb_array_elements(js) e
) s
group by 1;
consumable | amounts
---------------------------------+--------------------------------------
Mitsu 90mm ODEX Pilot Bit | {"2017-02-17": 3}
BOP Rubber | {"2017-02-17": 3}
NWJ Long Saver Sub Pin x Box | {"2017-02-17": 70, "2017-02-18": 13}
Methyl Hydrate - Per Litre | {"2017-02-17": 63}
Cyclone Discharge Hose Assembly | {"2017-02-17": 6}
(5 rows)
使用in this post所述的函数create_jsonb_pivot_view()
。
您必须使用上述数据创建一个新表来使用该功能,例如:
drop table if exists my_new_table;
create table my_new_table as
with test(js) as (
--
-- the above query
---
group by 1;
select create_jsonb_pivot_view('my_new_table', 'consumable', 'amounts');
select *
from my_new_table_view
order by 1;
consumable | 2017-02-17 | 2017-02-18
---------------------------------+------------+------------
BOP Rubber | 3 |
Cyclone Discharge Hose Assembly | 6 |
Methyl Hydrate - Per Litre | 63 |
Mitsu 90mm ODEX Pilot Bit | 3 |
NWJ Long Saver Sub Pin x Box | 70 | 13
(5 rows)
您可以使用此查询在不使用DDL的情况下尽可能接近所需格式的结果(假设the_data
包含问题中的数据):
with aux as (
select
e->>'consumable' as consumable,
e->>'amount' as amount,
e->>'consumed_date' as consumed_date
from the_data,
lateral jsonb_array_elements(js) e
)
select
null as consumable,
array_agg(distinct consumed_date order by consumed_date) as amounts
from aux
union all
select
consumable,
array_agg(amount order by consumed_date) as amounts
from (
select distinct t1.consumed_date, t2.consumable
from aux t1
cross join aux t2
) s
left join aux t using(consumed_date, consumable)
group by 1
order by 1 nulls first;
consumable | amounts
---------------------------------+-------------------------
| {2017-02-17,2017-02-18}
BOP Rubber | {3,NULL}
Cyclone Discharge Hose Assembly | {6,NULL}
Methyl Hydrate - Per Litre | {63,NULL}
Mitsu 90mm ODEX Pilot Bit | {3,NULL}
NWJ Long Saver Sub Pin x Box | {70,13}
(6 rows)