我的表有很多行,每行包含一个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'的数组值?
非常感谢任何和所有帮助!谢谢!
答案 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;