生成含有在使用T-SQL其他两个JSON串
说我有两个JSON字符串如下差异的JSON字符串:生成含有在使用T-SQL其他两个JSON串
[{"RowId":102787,"UserId":1,"Activity":"This is another test","Timestamp":"2017-11-25T14:37:30.3700000"}]
[{"RowId":102787,"UserId":2,"Activity":"Testing the Update function","Timestamp":"2017-11-25T14:37:30.3700000"}]
都具有相同的属性,但两个第二串中的属性有与第一个(UserId和Activity)不同的值。是否有可能在Azure SQL数据库T-SQL中生成第三个JSON字符串,该字符串包含第二个字符串中与第一个字符串不同的值?换句话说,我想一个字符串返回,看起来像这样:
[{"UserId":2,"Activity":"Testing the Update function"}]
此外,该解决方案应该假设在JSON字符串的属性是不知道。我需要这是任何两个JSON字符串的通用解决方案。
在Azure上没有尝试过,但它似乎在SQL Server 2017上工作 除了通过字符串操作,可能还有一种更优雅的方式来获得最终的JSON字符串,也许我们可以通过更好的方式更新答案。
-- Expected : [{"UserId":2,"Activity":"Testing the Update function"}]
DECLARE @jsonA NVARCHAR(MAX) = '[{"RowId":102787,"UserId":1,"Activity":"This is another test","Timestamp":"2017-11-25T14:37:30.3700000"}]'
,@jsonB NVARCHAR(MAX) = '[{"RowId":102787,"UserId":2,"Activity":"Testing the Update function","Timestamp":"2017-11-25T14:37:30.3700000"}]'
,@result NVARCHAR(MAX) = ''
SELECT @jsonA = REPLACE(REPLACE(@jsonA, ']', ''), '[', '')
,@jsonB = REPLACE(REPLACE(@jsonB, ']', ''), '[', '')
;WITH DSA AS
(
SELECT *
FROM OPENJSON(@jsonA)
)
,DSB AS
(
SELECT *
FROM OPENJSON(@jsonB)
)
SELECT @result += CONCAT (
'"', B.[key], '":'
,IIF(B.[type] = 2, B.[value], CONCAT('"', B.[value], '"')) -- havent checked types other than 1 and 2; think there's a bool type?
,','
)
FROM DSA A
JOIN DSB B ON A.[key] = B.[key]
WHERE A.[value] != B.[value]
SELECT CONCAT('[{', LEFT(@result, LEN(@result) - 1), '}]')
你可以使用:
DECLARE @json1 NVARCHAR(MAX) =
'[{"RowId":102787,"UserId":1,"Activity":"This is another test","Timestamp":"2017-11-25T14:37:30.3700000"}]';
DECLARE @json2 NVARCHAR(MAX) =
'[{"RowId":102787,"UserId":2,"Activity":"Testing the Update function","Timestamp":"2017-11-25T14:37:30.3700000"}]';
查询:
WITH cte1 AS (
SELECT *
FROM OPENJSON(@json1)
WITH (RowId INT, UserId INT, Activity NVARCHAR(MAX), Timestamp DATETIME2(7)))
, cte2 AS (
SELECT *
FROM OPENJSON(@json2)
WITH (RowId INT, UserId INT, Activity NVARCHAR(MAX), Timestamp DATETIME2(7)))
SELECT
RowId = NULLIF(c2.RowId, c1.RowId)
,UserId = NULLIF(c2.UserId, c1.UserId)
,Activity = NULLIF(c2.Activity, c1.Activity)
,Timestamp = NULLIF(c2.Timestamp, c1.Timestamp)
FROM cte1 c1
CROSS JOIN cte2 c2
FOR JSON AUTO;
输出:
[{"UserId":2,"Activity":"Testing the Update function"}]
谢谢。我改变我的帖子,澄清解决方案不应该假设我知道属性是什么,因为我不知道。这需要是一个通用的解决方案。 –
**对于downvoter **原始问题非常具体。对于输入得到输出,所以我的答案是正确的。我的答案后有一个编辑来扩展JSON独立的解决方案(也许它在纯T-SQL中是可行的,但我怀疑它)。留下评论是很好的做法,有助于改善这个和未来的答案。 – lad2025
谢谢。非常好的工作,这在Azure下工作。我不明白JSON的细微差别。你的意见是什么意思,“没有检查过除1和2以外的类型,认为是bool类型?” –
@RandyMinder; JSON中用于数字或字符串的类型确定值是否以引号提供。我认为JSON,因为它的根,可能有第三种类型:布尔值。只是说我没有编码字符串和数字以外的任何可能性。希望清除东西:) – MarkD
明白了。我在周末进行了一些研究,并对代码进行了一些调整,并按照我需要的方式工作。谢谢你的帮助。 –