Reputation: 430
I have a column with JSON arrays like below:
{data=[{"name":"col1","min":0,"max":32,"avg":29},
{"name":"col2","min":1,"max":35,"avg":21},
{"name":"col3","min":4,"max":56,"avg":34}]}
I'm trying to parse the array and extract specific values based on conditions. For example
value of "min"
where "name"="col1"
: 0
value of "avg"
where "name"="col3"
: 34
Does anyone have a solution for that?
Upvotes: 6
Views: 9466
Reputation: 103
I tried using the solution mentioned by @mingdinghan as it was the exact solution I was looking for. However, I ended up getting errors.
I made changes to the above code & was successful in getting the solution. Below is the solution if anyone is facing issue with the above code.
with mydata as (
select '[{"name":"col1","min":0,"max":32,"avg":29},
{"name":"col2","min":1,"max":35,"avg":21},
{"name":"col3","min":4,"max":56,"avg":34}]' jsonobj
)
select
max(case when a.name = 'col1' then a.min end) min_col1,
max(case when a.name = 'col3' then a.avg end) avg_col3
from mydata
CROSS JOIN
UNNEST(
CAST(json_parse(jsonobj) as array(ROW(name VARCHAR, min INTEGER, max INTEGER, avg INTEGER))
)
) as x(a)
Result is still the same as above.
Upvotes: 1
Reputation: 11
Following up on the above question from @siraj-alam, and extending on the answer by @leftjoin, if the data is a JSON array, i.e.
with mydata as (
select '[{"name":"col1","min":0,"max":32,"avg":29},
{"name":"col2","min":1,"max":35,"avg":21},
{"name":"col3","min":4,"max":56,"avg":34}]' json
)
This query gives the same answer
select max(case when x.name = 'col1' then x.min end) min_col1,
max(case when x.name = 'col3' then x.avg end) avg_col3
from mydata
CROSS JOIN
UNNEST(
CAST(
JSON_EXTRACT(json,'$')
as ARRAY(ROW(name VARCHAR, min INTEGER, max INTEGER, avg INTEGER))
)
) as x(name, min, max, avg) --column aliases
min_col1 avg_col3
0 34
Upvotes: 1
Reputation: 38325
Your JSON is not valid one. it should be {"data":[
not {data = [
If JSON is valid ( you can easily fix it in a subquery ), extract data, cast it to array(row) and get values using CASE expressions. I added max() aggregation here to remove NULL records and get all required values in single row, you can use filter instead (for example where x.name = 'col1'
), depending on what you need:
with mydata as (
select '{"data":[{"name":"col1","min":0,"max":32,"avg":29},
{"name":"col2","min":1,"max":35,"avg":21},
{"name":"col3","min":4,"max":56,"avg":34}]}' json
)
select max(case when x.name = 'col1' then x.min end) min_col1,
max(case when x.name = 'col3' then x.avg end) avg_col3
from mydata
CROSS JOIN
UNNEST(
CAST(
JSON_EXTRACT(json,'$.data')
as ARRAY(ROW(name VARCHAR, min INTEGER, max INTEGER, avg INTEGER))
)
) as x(name, min, max, avg) --column aliases
Result:
min_col1 avg_col3
0 34
Upvotes: 5