简体   繁体   中英

SQL Server: Compare json and find newly added, changed and deleted records

I want to compare two json in SQL Server and want to find the newly added, modified and deleted values.

Note: input cif_id order is not defined.

For example I have below old and new json:

old

{
 "cifs":[
    {
      "cif_id":"1",
      "bank_code":"110"
    },
    {
      "cif_id":"2",
      "bank_code":"120"
    },
    {
      "cif_id":"3",
      "bank_code":"130"
    }
  ]
}

and new/changed value

{
 "cifs":[
    {
      "cif_id":"1",
      "bank_code":"111"
    },
    {
      "cif_id":"2",
      "bank_code":"122"
    },
    {
      "cif_id":"4",
      "bank_code":"140"
    }
  ]
}

Here cif_id 1 and 2 are modified, 3 is deleted and 4 is added.

My returned value will be used by UI team to show on page. I can use stored procedure or function or plain SQL and my return should be in json format.

Result:

{
  "added":[
     {
      "cif_id":"4",
      "bank_code":"140"
    }
  ],
  "modified":[
     {
      "cif_id":"1",
      "bank_code":"111"
    },
    {
      "cif_id":"2",
      "bank_code":"122"
    }
  ],
  "deleted":[
     {
      "cif_id":"3",
      "bank_code":"130"
    }
  ]
}

A possible approach:

DECLARE @old nvarchar(max) = N'{
 "cifs": [
    {"cif_id":"1", "bank_code":"110"},
    {"cif_id":"2", "bank_code":"120"},
    {"cif_id":"3", "bank_code":"130"}
  ]
}'
DECLARE @new nvarchar(max) = N'{
 "cifs": [
    {"cif_id":"1", "bank_code":"111"},
    {"cif_id":"2", "bank_code":"122"},
    {"cif_id":"4", "bank_code":"140"}
  ]
}'

; WITH OldCTE AS (
   SELECT *
   FROM OPENJSON(@old, '$.cifs') WITH (
      cif_id nvarchar(1) '$.cif_id',
      bank_code nvarchar(3) '$.bank_code'
   )
), NewCTE AS (
   SELECT *
   FROM OPENJSON(@new, '$.cifs') WITH (
      cif_id nvarchar(1) '$.cif_id',
      bank_code nvarchar(3) '$.bank_code'
   )
)
SELECT
   added = (
      SELECT cif_id, bank_code
      FROM NewCTE 
      WHERE cif_id NOT IN (SELECT cif_id FROM OldCTE)
      FOR JSON AUTO
   ),
   modified = (
      SELECT n.cif_id, n.bank_code 
      FROM NewCTE n
      INNER JOIN OldCTE o ON n.cif_id = o.cif_id AND n.bank_code <> o.bank_code
      FOR JSON AUTO
   ),
   deleted = (
      SELECT cif_id, bank_code
      FROM OldCTE 
      WHERE cif_id NOT IN (SELECT cif_id FROM NewCTE)
      FOR JSON AUTO
   )
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER

Result:

{
   "added":[
      {
         "cif_id":"4",
         "bank_code":"140"
      }
   ],
   "modified":[
      {
         "cif_id":"1",
         "bank_code":"111"
      },
      {
         "cif_id":"2",
         "bank_code":"122"
      }
   ],
   "deleted":[
      {
         "cif_id":"3",
         "bank_code":"130"
      }
   ]
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM