2017-05-10 119 views
1

我有一个名为cust_data的表,它存储了id和JSON对象。我想写Postgres的select语句获取:Postgres查询JSON数组

  1. 选择所有的id其中“性别”:“女”是不存在的人数组[这应该从下面的数据返回ID#3]
  2. 选择所有的id其中, “性别”: “女性” 是本和 “状态”: “已婚”

表[这应该从下面的数据返回ID#2]: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" 
      } 
      ] 
     } 
+0

你看官方的Postgres页:https://www.postgresql.org/docs/9.3/static/functions-json .html –

+0

是的。但它拉出所有记录。这里是查询 - 从cust_data t,jsonb_array_elements(t.connections - >'persons')的SELECT id AS elem WHERE elem - >>'gender'!='female'; – user842122

+0

请检查人员。在你的例子中它是大写字母。而在查询时,它是用小写字母写的。 –

回答

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 

我希望上面的语句将解决您的问题。

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); 
+0

谢谢!此查询不提取人员数组为空的ID – user842122

+0

请参阅编辑答案。 – klin