如何迭代PostgreSQL jsonb数组值以便在查询中进行匹配

时间:2017-09-14 17:55:44

标签: json postgresql

我的表有很多行,每行包含一个jsonb对象。

此对象包含一个数组,其中可能存在多个具有相同名称但值不同的键。

我的目标是扫描整个表并验证哪些行包含此json对象数组中的重复值。

第1行示例数据:

{
    "Name": "Bobb Smith",
    "Identifiers": [
        {
            "Content": "123",
            "RecordID": "123",
            "SystemID": "Test",
            "LastUpdated": "2017-09-12T02:23:30.817Z"
        },
        {
            "Content": "abc",
            "RecordID": "abc",
            "SystemID": "Test",
            "LastUpdated": "2017-09-13T10:10:21.598Z"
        },
        {
            "Content": "def",
            "RecordID": "def",
            "SystemID": "Test",
            "LastUpdated": "2017-09-13T10:10:21.598Z"
        }
    ]
}

第2行示例数据:

{
    "Name": "Bob Smith",
    "Identifiers": [
        {
            "Content": "abc",
            "RecordID": "abc",
            "SystemID": "Test",
            "LastUpdated": "2017-09-13T10:10:26.020Z"
        }
    ]
}

我当前的查询最初用于根据名称值查找重复项,但是,如果名称可能会被删除,则使用记录ID是一种更全面的方法。

但是,我无法弄清楚如何基本上迭代每个记录ID'在每一行中并比较记录ID'彼此记录ID'在同一个表中的每一行中找到匹配项。

我当前的查询匹配'姓名':

discard temporary;

with dupe as (
    select 
    json_document->>'Name' as name, 
    json_document->'Identifiers'->0->'RecordID' as record_id, 
    from staging
)


 select name as "Name", record_id::text as "Record ID"
 from dupe da
 where ( select count(*) from dupe db where db.name = da.name) > 1
 order by full_name;

上面的查询会返回匹配的行,如果'名称'两行中的字段包含相同的“Bob'”拼写。

我需要使用' RecordID'的嵌套值来实现相同的功能。字段。

这里的问题是     json_document->'Identifiers'->0->'RecordID' 只返回' RecordID'在数组中的索引0处。

例如,这不起作用:

discard temporary;
with dupe as (
    select 
    json_document->>'Name' as name, 
    json_document->'Identifiers'->0->'RecordID' as record_id, 
    from staging
)

select name as "Name", record_id::text as "Record ID"
from dupe da
where ( select count(*) from dupe db where db.record_id = da.record_id) > 1
order by full_name;

...因为查询只检查' RecordID' '标识符'的索引0处的值阵列。

我怎么能基本上执行类似的事情     SELECT json_document@>'RecordID' 为了让我的查询检查“标识符”中的每个索引。 ' RecordID'的数组值?

非常感谢任何和所有帮助!谢谢!

  • 我希望只使用Postgres查询来完成此操作,而不是通过使用外部语言访问此数据。 (Python等)

1 个答案:

答案 0 :(得分:0)

我通过基本上执行'unnest()'解决了这个问题 - 就像我的嵌套jsonb数组上的jsonb_array_elements()一样。

通过在子查询中执行此操作,然后使用原始查询的变体扫描这些结果,我能够实现我想要的结果。

这是我想出的。

with dupe as (
select
json_document->>'Name' as name,
identifiers->'RecordID' as record_id
from (
  select *,  
  jsonb_array_elements(json_document->'Identifiers') as identifiers
  from staging
) sub
group by record_id, json_document
order by name
) 

select * from dupe da where (select count(*) from dupe db where 
db.record_id = da.record_id) > 1;