2

I am trying to extract value from JSON ARRAY as below

  with `project.dataset.table` as (
  select '{"fruit":[{"apples":"5","oranges":"10","pear":"20"},
                    {"apples":"5","oranges":"4"},
                    {"apples":"5","oranges":"9","pear":"40"}]}' as json union all
  select '{"fruit":[{"lettuce":"7","kale": "8"}]}' 
)

select json, if(regexp_contains(json, '"apples":"5"'), (SELECT 
ARRAY_AGG(json_extract_scalar(arr, '$.oranges') ignore nulls)
from 
UNNEST(json_extract_ARRAY(json, '$.fruit')) as arr ), null) as oranges,
if(regexp_contains(json, '"apples":"5"'), (SELECT 
ARRAY_AGG(json_extract_scalar(arr, '$.pear') ignore nulls)
from 
UNNEST(json_extract_ARRAY(json, '$.fruit')) as arr ), null) as pear,
from `project.dataset.table` 

It gives output as below enter image description here

I am expecting output like

json oranges pear
{"fruit":[{"apples":"5","oranges":"10","pear":"20"},{"apples":"5","oranges":"4"},{"apples":"5","oranges":"9","pear":"40"}]} 10 20
4 null
9 40
{"fruit":[{"lettuce":"7","kale": "8"}]}. null null

2 Answers 2

1

Consider below approach with more explicit alignment of respective entries

select json, 
  array(
    select 
      if(
        json_extract_scalar(val, '$.apples') = '5',
        struct(
          json_extract_scalar(val, '$.oranges') as oranges,
          json_extract_scalar(val, '$.pear') as pear
        ),
        struct(null, null)
      )
    from t.arr val
  ) fruits
from `project.dataset.table`, 
unnest([struct(json_extract_array(json, '$.fruit') as arr)]) t      

It is less verbose and has output of fruits as a repeated record as opposed to two arrays
If applied to sample data in your question output is

enter image description here

In case if you really need to keep output is separate columns - use below

select json, 
  array(
    select 
      if(
        json_extract_scalar(val, '$.apples') = '5',
        ifnull(json_extract_scalar(val, '$.oranges'), '0'),
        '0'
      )
    from t.arr val
  ) as oranges,
  array(
    select 
      if(
        json_extract_scalar(val, '$.apples') = '5',
        ifnull(json_extract_scalar(val, '$.pear'), '0'),
        '0'
      )
    from t.arr val
  ) as pear
from `project.dataset.table`, 
unnest([struct(json_extract_array(json, '$.fruit') as arr)]) t       

with output

enter image description here

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for you help :) It worked for me!
0

When working with array_agg

an error is raised if an array in the final query result contains a NULL element.

You can try using a string 'null' like this:

with `project.dataset.table` as (
  select '{"fruit":[{"apples":"5","oranges":"10","pear":"20"},{"apples":"5","oranges":"4"},{"apples":"5","oranges":"9","pear":"40"}]}' as json union all
  select '{"fruit":[{"lettuce":"7","kale": "8"}]}' 
)
select 
  json,
  if( regexp_contains(json, '"apples":"5"'),
    (SELECT ARRAY_AGG(ifnull(json_extract_scalar(arr, '$.oranges'), 'null')) from UNNEST(json_extract_ARRAY(json, '$.fruit')) as arr ),
    ['null']
  ) as oranges,
  if( regexp_contains(json, '"apples":"5"'),
    (SELECT ARRAY_AGG(ifnull(json_extract_scalar(arr, '$.pear'), 'null')) from UNNEST(json_extract_ARRAY(json, '$.fruit')) as arr ),
    ['null']
  ) as pear,
from `project.dataset.table`

enter image description here

Comments

Your Answer

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.