【问题标题】:Remove a known subset of nodes from JSON, in SQLAzure在 SQLAzure 中从 JSON 中删除已知的节点子集
【发布时间】:2018-09-07 20:37:23
【问题描述】:

从前有一行数据(大大简化,实际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
    }'

我想知道是否有办法从 ID 2 记录中删除多余的行。

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

有些 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
    }'

我已经开始使用https://dba.stackexchange.com/questions/168303/can-sql-server-2016-extract-node-names-from-json 来获取我想从 ID 2 中删除的 ID 1 中的节点名称列表,只是不知道如何将它们从 ID 2 的 JSON 中剥离出来——大概是反序列化,减少和重新序列化序列?

【问题讨论】:

    标签: sql json sql-server azure-sql-database


    【解决方案1】:

    你可以按照这个方法:

    1. 在具有id=1 值的行上获取要替换为openjson 的键
    2. 使用cross apply 过滤带有id>1 的行中的键
    3. 使用STRING_AGGgroup by重建没有不需要的键的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
    

    结果:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-30
      • 1970-01-01
      • 1970-01-01
      • 2023-02-23
      • 2018-07-19
      相关资源
      最近更新 更多