【问题标题】:How get value from jsonb in Postgres with queries on not ordered json arrays如何通过查询未排序的 json 数组从 Postgres 中的 jsonb 获取值
【发布时间】:2022-07-02 08:56:43
【问题描述】:

我在 Postgres jsonb 字段中有这样的数据。每个工人可以有多个电话号码。工人可以有或没有工作的电话。工作的电话号码可以是数组中的第一个或最后一个(不排序)。

INSERT INTO "contacts" ("id", "json") VALUES
(101, ' 
{
    "add-date": "2022-06-04",
    "workers": [
        {
            "name": "Alex",
            "phones": [
                { "type": "HOME", "number": 926117171 },                
                { "type": "WORK", "number": 916100203 },                
                { "type": "CELL", "number": 911463212 }             
            ]
        },
        {
            "name": "Maria",
            "phones": [
                { "type": "HOME", "number": 919351948 },
                { "type": "WORK", "number": 915532355 }
            ]
        }
    ]
}
'),
(102, '
{
    "add-date": "2022-06-05",
    "workers": [
        {
            "name": "Pablo",
            "phones": [
                { "type": "CELL", "number": 913456719 }
            ]
        },
        {
            "name": "Nina",
            "phones": [
                { "type": "WORK", "number": 915532321 },
                { "type": "CELL", "number": 919455354 }
            ]
        }
    ]
}
');

我需要选择并显示有工作编号的工人表,如下所示:

Alex   | 916100203
Maria  | 915532355
Nina   | 915532321

我只能在 Postresql 中使用 SQL+jsonb 查询吗?如何做?

【问题讨论】:

  • 使用适当的规范化数据模型会容易得多。

标签: sql json postgresql jsonb


【解决方案1】:

以下是这样做的:

select c.id, w.value ->> 'name' as name,
       jsonb_path_query_first(w.value, '$.phones[*] ? (@.type == "WORK")') ->> 'number' as work_number
from contacts c
  cross join jsonb_array_elements("json" -> 'workers') as w(value)
where w.value @> '{"phones": [{"type": "WORK"}]}'
;

cross join jsonb_array_elements("json" -> 'workers') 从 JSON 值中提取所有工作人员作为行。然后 where 子句限制那些实际包含工作编号的行。

这会产生这样的结果:

id  | value                                                                                                                                            
----+--------------------------------------------------------------------------------------------------------------------------------------------------
101 | {"name": "Alex", "phones": [{"type": "HOME", "number": 926117171}, {"type": "WORK", "number": 916100203}, {"type": "CELL", "number": 911463212}]}
101 | {"name": "Maria", "phones": [{"type": "HOME", "number": 919351948}, {"type": "WORK", "number": 915532355}]}                                      
102 | {"name": "Nina", "phones": [{"type": "WORK", "number": 915532321}, {"type": "CELL", "number": 919455354}]}                                       

现在 SELECT 列表将工人的姓名提取为一列,并使用 JSON 路径查询来查找电话数组中的第一个 WORK 号码。

如果工作人员的 WORK 电话有多个数组元素,这将无法正常工作。

Online example

【讨论】:

    猜你喜欢
    • 2015-11-28
    • 2018-08-02
    • 1970-01-01
    • 2020-10-14
    • 2019-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-17
    相关资源
    最近更新 更多