Search code examples
sqljsonpostgresqlpostgresql-9.4jsonb

Postgres select where in json array containing json


I have a table in a postgresql 9.4 database with a jsonb field. Some example rows:

[{"name": "145119603", "numberOfCarrot": 2}]
[{"name": "1884595530", "numberOfCarrot": 1}]
[{"name": "363058213", "numberOfCarrot": 1}] 
[{"name": "1427965764", "numberOfCarrot": 1}]
[{"name": "193623800", "numberOfCarrot": 43}, {"name": "419955814", "numberOfCarrot": 0}]
[{"name": "624635532", "numberOfCarrot": 0}, {"name": "1884595530", "numberOfCarrot": 1}]
[{"name": "791712670", "numberOfCarrot": 1}]
[{"name": "895207852", "numberOfCarrot": 0}]
[{"name": "144695994", "numberOfCarrot": 3}, {"name": "384217055", "numberOfCarrot": 23}]
[{"name": "1079725696", "numberOfCarrot": 10}]
  • How can I find the max numberOfCarrot of all row?
  • How can I find the max numberOfCarrot of one row?
  • How can I find the row where the numberOfCarrot is superior or inferior to something ?
  • How can I find the element in the json array where the numberOfCarrot is superior or inferior to something ?

Solution

  • You need a unique column (usually a primary key, let's say id), so your data should look like this:

    (1, '[{"name": "145119603", "numberOfCarrot": 2}]'),
    (2, '[{"name": "1884595530", "numberOfCarrot": 1}]'),
    ...
    

    Use jsonb_array_elements() in lateral join. Examples:

    select max(value->>'numberOfCarrot')::int
    from my_table,
    jsonb_array_elements(jdata);
    
     max 
    -----
      43
    (1 row) 
    
    select id, max((value->>'numberOfCarrot')::int)
    from my_table,
    jsonb_array_elements(jdata)
    group by 1
    order by 1;
    
     id | max 
    ----+-----
      1 |   2
      2 |   1
      3 |   1
      4 |   1
      5 |  43
      6 |   1
      7 |   1
      8 |   0
      9 |  23
     10 |  10
    (10 rows)
    

    How to use where:

    select id, value->>'numberOfCarrot' as "numberOfCarrot"
    from my_table,
    jsonb_array_elements(jdata)
    where (value->>'numberOfCarrot')::int > 20;
    
     id | numberOfCarrot 
    ----+----------------
      5 | 43
      9 | 23
    (2 rows)
    
    select id, array_agg(value->>'numberOfCarrot') as "numberOfCarrot"
    from my_table,
    jsonb_array_elements(jdata)
    where (value->>'numberOfCarrot')::int > 2
    group by 1
    order by 1;
    
     id | numberOfCarrot 
    ----+----------------
      5 | {43}
      9 | {3,23}
     10 | {10}
    (3 rows)