Postgres查询JSON数组

use*_*122 1 arrays postgresql json postgresql-9.1 jsonb

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

  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"
            }   
          ]
        }
Run Code Online (Sandbox Code Playgroud)

kli*_*lin 5

您可以使用布尔聚合函数:

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)
Run Code Online (Sandbox Code Playgroud)

在这里测试一下.


如果数组可能为空,则应使用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);
Run Code Online (Sandbox Code Playgroud)