2017-11-25 103 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