2

One of the great things about postgres is that it allows indexing into a json object.

I have a column of data formatted a little bit like this:

{"Items":
 [
 {"RetailPrice":6.1,"EffectivePrice":0,"Multiplier":1,"ItemId":"53636"},
 {"RetailPrice":0.47,"EffectivePrice":0,"Multiplier":1,"ItemId":"53404"}
 ]
}

What I'd like to do is find the average RetailPrice of each row with these data.

Something like

select avg(json_extract_path_text(item_json, 'RetailPrice')) 

but really I need to do this for each item in the items json object. So for this example, the value in the queried cell would be 3.285

How can I do this?

Erwin Brandstetter
668k159 gold badges1.2k silver badges1.3k bronze badges
asked Aug 26, 2014 at 18:20
3
  • Do not use JSON for well structured data. Very Bad Idea. Commented Aug 26, 2014 at 18:24
  • The problem is, the data is very difficult to parse. In the full data set, "Items" is just one attribute of a larger JSON object. Plus, the attributes of each record vary widely, there are probably fifty different attributes per record, and you never know which will be present at any given time. I'd love to talk with you more about it if you're willing to help me figure out what to use to store it in the db Commented Aug 26, 2014 at 19:18
  • 1
    So it is not well structured as in your sample. As the alternatives are somewhat involved then JSON might be a good option. Check this answer: stackoverflow.com/a/876459/131874 Commented Aug 26, 2014 at 22:53

1 Answer 1

3

Could work like this:

WITH cte(tbl_id, json_items) AS ( 
 SELECT 1
 , '{"Items": [
 {"RetailPrice":6.1,"EffectivePrice":0,"Multiplier":1,"ItemId":"53636"}
 ,{"RetailPrice":0.47,"EffectivePrice":0,"Multiplier":1,"ItemId":"53404"}]}'::json
 )
SELECT tbl_id, round(avg((elem->>'RetailPrice')::numeric), 3) AS avg_retail_price
FROM cte c
 , json_array_elements(c.json_items->'Items') elem
GROUP BY 1;

The CTE just substitutes for a table like:

CREATE TABLE tbl (
 tbl_id serial PRIMARY KEY
 , json_items json
);
answered Aug 27, 2014 at 23:21
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.