2017-11-25 180 views
0

说我有两个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字符串的通用解决方案。

回答

1

在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), '}]') 
+0

谢谢。非常好的工作,这在Azure下工作。我不明白JSON的细微差别。你的意见是什么意思,“没有检查过除1和2以外的类型,认为是bool类型?” –

+0

@RandyMinder; JSON中用于数字或字符串的类型确定值是否以引号提供。我认为JSON,因为它的根,可能有第三种类型:布尔值。只是说我没有编码字符串和数字以外的任何可能性。希望清除东西:) – MarkD

+0

明白了。我在周末进行了一些研究,并对代码进行了一些调整,并按照我需要的方式工作。谢谢你的帮助。 –

-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; 

DBFiddle Demo

输出:

[{"UserId":2,"Activity":"Testing the Update function"}] 
+0

谢谢。我改变我的帖子,澄清解决方案不应该假设我知道属性是什么,因为我不知道。这需要是一个通用的解决方案。 –

+0

**对于downvoter **原始问题非常具体。对于输入得到输出,所以我的答案是正确的。我的答案后有一个编辑来扩展JSON独立的解决方案(也许它在纯T-SQL中是可行的,但我怀疑它)。留下评论是很好的做法,有助于改善这个和未来的答案。 – lad2025

相关问题