sql - How do I return a jsonb array and array of objects from my data? -


i have following table:

create table mytable (   id       serial primary key , employee text unique not null , data     jsonb ); 

with following data:

insert mytable (employee, data) values  ('jim', '{"sales_tv": [{"value": 10, "yr": "2010", "loc": "us"}, {"value": 5, "yr": "2011", "loc": "europe"}, {"value": 40, "yr": "2012", "loc": "asia"}], "sales_radio": [{"value": 11, "yr": "2010", "loc": "us"}, {"value": 8, "yr": "2011", "loc": "china"}, {"value": 76, "yr": "2012", "loc": "us"}], "another_key": "another value"}'),  ('rob', '{"sales_radio": [{"value": 7, "yr": "2014", "loc": "japan"}, {"value": 3, "yr": "2009", "loc": "us"}, {"value": 37, "yr": "2011", "loc": "us"}], "sales_tv": [{"value": 4, "yr": "2010", "loc": "us"}, {"value": 18, "yr": "2011", "loc": "europe"}, {"value": 28, "yr": "2012", "loc": "asia"}], "another_key": "another value"}') 

notice there other keys in there besides "sales_tv" , "sales_radio". queries below need focus on "sales_tv" , "sales_radio".

i need find sales jim 2012. starts "sales_" , put in object (just need product sold , value). e.g.:

    employee   | sales_     jim        | {"sales_tv": 40, "sales_radio": 76} 

i've got:

select * mytable,   (select l.key, l.value mytable, lateral jsonb_each_text(data) l     key 'sales_%') a,   jsonb_to_recordset(a.value::jsonb) d(yr text, value float)   mytable.employee = 'jim'   , d.yr = '2012' 

but can't seem jim's data. instead get:

employee | key         |  value -------- |------       | ----- jim      | sales_tv    |  [{"yr": "2010", "loc": "us", "value": 4}, {"yr": "2011", "loc": "europe", "value": 18}, {"yr": "2012", "loc": "asia", "value": 28}] jim      | sales_tv    |  [{"yr": "2010", "loc": "us", "value": 10}, {"yr": "2011", "loc": "europe", "value": 5}, {"yr": "2012", "loc": "asia", "value": 40}] jim      | sales_radio |  [{"yr": "2010", "loc": "us", "value": 11}, {"yr": "2011", "loc": "china", "value": 8}, {"yr": "2012", "loc": "us", "value": 76}] 

you treat result of first join json, not text string, use jsonb_each() instead of jsonb_each_text():

select t.employee, json_object_agg(a.k, d.value) sales   mytable t join   lateral jsonb_each(t.data) a(k,v) on a.k 'sales_%' join   lateral jsonb_to_recordset(a.v) d(yr text, value float) on d.yr = '2012'  t.employee = 'jim'  -- works because employee unique group  1; 

group 1 shorthand group t.employee.
result:

employee | sales ---------+-------- jim      | '{ "sales_tv" : 40, "sales_radio" : 76 }' 

i untangled , simplified query.

json_object_agg() instrumental in aggregating name/value pairs json object. optionally cast jsonb if need - or use jsonb_object_agg() in postgres 9.5 or later.

using explicit join syntax attach conditions in obvious place.
the same without explicit join syntax:

select t.employee, json_object_agg(a.k, d.value) sales   mytable t      , jsonb_each(t.data)      a(k,v)       , jsonb_to_recordset(a.v) d(yr text, value float)  t.employee = 'jim' ,    a.k 'sales_%' ,    d.yr = '2012' group  1; 

Comments

Popular posts from this blog

python - Healpy: From Data to Healpix map -

c - Bitwise operation with (signed) enum value -

xslt - Unnest parent nodes by child node -