2017-08-21 60 views
2

參照微軟提供的例子:解析JSON在SQL Server

DECLARE @json NVARCHAR(MAX) 
SET @json = 
N'[ 
     { "id" : 2,"info": { "name": "John", "surname": "Smith" }, "age": 25 }, 
     { "id" : 5,"info": { "name": "Jane", "surname": "Smith" }, "dob": "2005-11-04T12:00:00" } 
]' 

SELECT * 
FROM OPENJSON(@json) 
    WITH (id int 'strict $.id', 
     firstName nvarchar(50) '$.info.name', lastName nvarchar(50) '$.info.surname', 
     age int, dateOfBirth datetime2 '$.dob') 

當JSON數據有一個數組裏面,例如:

DECLARE @json NVARCHAR(MAX) 
SET @json = 
N'[ 
     { "id" : 2,"info": { "name": "John", "surname": "Smith" }, 
     "Phones": ["123","345","678"] // like here 
     } 
]' 

有什麼辦法加入陣列解析後的數據得到的東西是這樣的:

Id  First Name  Last Name Phone 
2  John   Smith  123 
2  John   Smith  345 
2  John   Smith  678 

回答

3

OUTER APPLY這裏是你的朋友。讓我們混合使用兩種行,以獲得更好的效果。

DECLARE @json NVARCHAR(MAX) 
SET @json = N' 
[ 
    { 
    "id": 2, 
    "info": { 
     "name": "John", 
     "surname": "Smith" 
    }, 
    "age": 25, 
    "Phones": [ 
     "123", 
     "345", 
     "678" 
    ] 
    }, 
    { 
    "id": 5, 
    "info": { 
     "name": "Jane", 
     "surname": "Smith" 
    }, 
    "dob": "2005-11-04T12:00:00" 
    } 
]' 

SELECT id, [name], [surname], age, dateOfBirth, number 
FROM (
    SELECT * 
    FROM OPENJSON(@json) 
    WITH (
     id   INT    'strict $.id', 
     [name]  NVARCHAR(50) '$.info.name', 
     [surname] NVARCHAR(50) '$.info.surname', 
     age   INT, 
     dateOfBirth DATETIME2  '$.dob', 
     Phones  NVARCHAR(MAX) AS JSON 
    ) 
) AS people 
OUTER APPLY OPENJSON(Phones) 
WITH (
    number NVARCHAR(50) '$' 
) 

結果:

+----+------+---------+------+-----------------------------+--------+ 
| id | name | surname | age |   dateOfBirth   | number | 
+----+------+---------+------+-----------------------------+--------+ 
| 2 | John | Smith | 25 | NULL      | 123 | 
| 2 | John | Smith | 25 | NULL      | 345 | 
| 2 | John | Smith | 25 | NULL      | 678 | 
| 5 | Jane | Smith | NULL | 2005-11-04 12:00:00.0000000 | NULL | 
+----+------+---------+------+-----------------------------+--------+ 
+0

偉大的解決方案,我被困在這個'Phones NVARCHAR(MAX)AS JSON',所以實現它像value子句 – TheGameiswar

+0

@TheGameiswar:如果值的數量嚴格限制(和/或已知)明確地將它們從數組可能會比第二個'OPENJSON'快。但是我沒有經驗JSON解析的時間,所以現在不需要優化。 :-) –

+0

是的,你是對的,只是看到執行計劃,原Json的成本爲0,json低於outer apply的成本爲20 – TheGameiswar

2

你將不得不做兩遍:

  1. 提取每個人的數據和電話號碼留下數組作爲JSON
  2. 使用交叉/ OUTER APPLY解析每個人的電話號碼數組並加入結果

事情是這樣的:

DECLARE @json NVARCHAR(MAX) 
SET @json = 
N'[ 
    { "id" : 2,"info": { "name": "John", "surname": "Smith" }, "Phones": ["123","345","678"] }, 
    { "id" : 3,"info": { "name": "Jane", "surname": "Smith" }, "Phones": ["321","543"] } 
]'; 

WITH CTE AS (
    SELECT id, firstName, lastName, phones 
    FROM OPENJSON(@json) 
    WITH (
     id INT 'strict $.id', 
     firstName NVARCHAR(50) '$.info.name', 
     lastName NVARCHAR(50) '$.info.surname', 
     phones NVARCHAR(MAX) '$.Phones' AS JSON 
    ) 
) 
SELECT c.id, c.firstName, c.lastName, p.value as phone 
FROM CTE c 
    CROSS APPLY OPENJSON(c.phones) p 
3

嗯,你總是可以做這樣的事情:

SELECT ID, FirstName, LastName, value 
FROM OPENJSON(@json) 
WITH(ID int '$.id', 
    FirstName nvarchar(50) '$.info.name', 
    LastName nvarchar(50) '$.info.surname', 
    Phones nvarchar(max) '$.Phones' AS Json) 
CROSS APPLY OPENJSON(Phones) 

希望這有助於。