Postgres查询JSON数组

时间:2017-05-10 17:25:51

标签: arrays json postgresql postgresql-9.1 jsonb

我有一个名为cust_data的表,它存储id和JSON对象。我想编写postgres select语句来获取:

  1. 选择所有ID的“性别”:人员阵列中不存在“女性”[这应该从以下数据返回ID#3]
  2. 选择所有ID,其中“性别”:“女性”存在,“状态”:“已婚”[这应该从以下数据返回ID#2]
  3. 表:cust_data

    id(numeric) | connections (jsonb)
    ------------------------------
    
    1, {"Persons": [
                {
                  "personName": "Tom",
                  "gender": "Male",
                  "country": "USA",
                  "status":"single"
    
                },
                {
                "personName": "Harry",
                "gender": "Male",
                "country": "USA",
                "status":"single"
                },
                {
                "personName": "Lisa",
                "gender": "Female",
                "country": "Mexico",
                "status":"single"
                  }    
              ]
            }
    
            2,{
              "Persons": [
                {
                  "personName": "Lisa",
                  "gender": "Male",
                  "country": "UK",
                  "status":"single"
                },
                {
                "personName": "Harry",
                "gender": "Male",
                "country": "USA",
                "status":"single"
                },
                {
                "personName": "Lisa",
                "gender": "Female",
                "country": "Mexico",
                "status":"married"
                  }    
              ]
            }
    
            3,{
              "Persons": [
                {
                  "personName": "Lisa",
                  "gender": "Male",
                  "country": "UK",
                  "status":"single"
                },
                {
                "personName": "Harry",
                "gender": "Male",
                "country": "USA",
                "status":"single"
                }   
              ]
            }
    

2 个答案:

答案 0 :(得分:5)

您可以使用boolean aggregate functions

select id
from cust_data,
lateral jsonb_array_elements(connections->'Persons')
group by 1
having not bool_or(value->>'gender' = 'Female');

 id 
----
  3
(1 row)

select id
from cust_data,
lateral jsonb_array_elements(connections->'Persons')
group by 1
having bool_or(value->>'gender' = 'Female' and value->>'status' = 'married');

 id 
----
  2
(1 row)

Test it here.

如果数组可能为空,则应使用left join ... on true代替lateral。也为coalesce()添加适当的聚合默认值,因为它们可以产生null,例如:

select id
from cust_data
left join jsonb_array_elements(connections->'Persons') on true
group by 1
having not coalesce(bool_or(value->>'gender' = 'Female'), false);

答案 1 :(得分:0)

查询1:

WITH test AS (
    SELECT id, jsonb_array_elements(t.connections->'Persons') AS elem
    FROM cust_data  t
), findFemale AS (
    SELECT DISTINCT id FROM test
   WHERE elem->>'gender' = 'Female'
) 
SELECT id FROM cust_data
WHERE id NOT IN  (select * from findFemale)

查询2:

 WITH test as (SELECT id, jsonb_array_elements(t.connections->'Persons') AS elem  
 from cust_data   t
 ) , findFemaleMarried as (
 select distinct id from test
 where 
 elem ->> 'gender' = 'Female' and elem ->> 'status' = 'married'
 )
 select * from findFemaleMarried

我希望以上查询可以解决您的问题。