在SQLAzure中从JSON中删除已知的节点子集

在SQLAzure中从JSON中删除已知的节点子集,sql,json,sql-server,azure-sql-database,Sql,Json,Sql Server,Azure Sql Database,从前,有一行数据被大量简化,实际的json数据是10KB+因此: ID, json 1, '{ "a1.arr": [1,2,3], "a1.boo": true, "a1.str": "hello", "a1.num": 123 }' 一个进程应该用主要不同的数据写入另一条记录: ID, json 2, '{ "a1.arr": [1,2,3], //from ID 1 "a2.arr": [4,5,6], //

从前,有一行数据被大量简化,实际的json数据是10KB+因此:

ID, json
1, '{
      "a1.arr": [1,2,3],
      "a1.boo": true,
      "a1.str": "hello",
      "a1.num": 123
    }'
一个进程应该用主要不同的数据写入另一条记录:

ID, json
2, '{
      "a1.arr": [1,2,3], //from ID 1
      "a2.arr": [4,5,6], //new (and so are all below)
      "a2.boo": false,
      "a2.str": "goodbye",
      "a2.num": 456
    }'
但由于一些外部错误,来自ID 1的原始json集最终也在ID 2中表示,因此现在该表如下所示:

ID, json
1, '{
      "a1.arr": [1,2,3],
      "a1.boo": true,
      "a1.str": "hello",
      "a1.num": 123
    }'
2, '{
      "a1.arr": [1,2,3],
      "a1.boo": true,    //extraneous
      "a1.str": "hello", //extraneous
      "a1.num": 123,     //extraneous
      "a2.arr": [4,5,6],
      "a2.boo": false,
      "a2.str": "goodbye",
      "a2.num": 456
    }'
我想知道是否有办法从ID2记录中删除多余的行

我相信ID1中的整个JSON字符串在ID2中表示为一个连续的块,因此字符串替换可以工作,但有可能发生了一些重新排序。但是,对应该保留的元素的处理有点混乱

还有一种可能是a1.*节点的某些值发生了轻微的更改,我没有进行区分,但我很乐意使用节点名称,而不是它们的值来评估是否应该删除节点。其中一个节点a1.arr应保留在ID 2中。因此,结果集应该如下所示:

ID, json
1, '{
      "a1.arr": [1,2,3],
      "a1.boo": true,
      "a1.str": "hello",
      "a1.num": 123
    }'
2, '{
      "a1.arr": [1,2,3],
      "a2.arr": [4,5,6],
      "a2.boo": false,
      "a2.str": "goodbye",
      "a2.num": 456
    }'

我已经开始尝试从ID 1中获取要从ID 2中删除的节点名列表,只是不知道如何从ID 2的JSON中删除它们-可能是一个反序列化、缩减和重新序列化序列?

您可以采用以下方法:

在id=1的行上获取要替换为openjson的键 使用交叉应用筛选id>1的行中的键 使用string_AGG和groupby在没有不需要的键的情况下重建json字符串 此代码应适用于:

declare @tmp table ([id] int, jsonValue nvarchar(max))
declare @source_json nvarchar(max)

insert into @tmp values
 (1, '{"a1.arr":[1,2,3],"a1.boo":true,"a1.str":"hello","a1.num":123}')
,(2, '{"a1.arr":[1,2,3],"a1.boo":true,"a1.str":"hello","a1.num":123,"a2.arr":[4,5,6],"a2.boo":false,"a2.str":"goodbye","a2.num":456}')
,(3, '{"a1.arr":[1,2,3],"a1.boo":true,"a1.str":"hello","a1.num":123,"a3.arr":[4,5,6],"a3.boo":false,"a3.str":"goodbye","a3.num":456}')

--get json string from id=1
select @source_json = jsonValue from @tmp where [id] = 1

--rebuild json string for id > 1 removing keys from id = 1
select t.[id],   
       '{' + STRING_AGG( '"' + g.[key] + '":"' + STRING_ESCAPE(g.[value], 'json')  + '"', ',') + '}' as [json]
from @tmp t cross apply openjson(jsonValue) g
where t.id > 1
    and g.[key] not in (select [key] from openjson(@source_json) where [key] <> 'a1.arr')
group by t.id
结果: