簡體   English   中英

將JSON字符串轉換為SQL Server中的規范化架構

[英]Convert JSON strings to normalized schema in SQL Server

我在Azure SQL Server數據庫中有一個表,它只是一個nvarchar(max)列,其中包含JSON字符串,如下所示,每行一個扁平化為一行(約200,000行)

{
    "username": "George84",
    "items": [{
            "type": 8625,
            "score": "90"
        }, {
            "type": 8418,
            "score": "84"
        }, {
            "type": 7818,
            "score": "90"
        }, {
            "type": 23,
            "score": "q"
        }
    ]
}

每條記錄都有一個用戶名和一個包含一個或多個條目的項目數組。 items數組中的每個條目都包含一個類型字段(整數)和一個得分字段(字符串)。 用戶名是唯一的。 多個用戶可能具有相同類型的項目,並且這些重復項可能具有相同的分數,也可能不具有相同的分數。

我想將其轉換為一組新的正確規范化的表,其架構如下所示:

架構圖

我知道我可以使用外部應用程序來完成它,但我希望利用SQL Server 2016的新JSON處理功能完全在數據庫/ TSQL中完成。

完成此轉換的最佳方法是什么?

這是我第一次使用Json和T-sql,但我覺得它很有趣,所以我認為可能有很多更好的解決方案,無論如何讓我們開始吧。

首先我需要一些數據開始,所以我將生成一些臨時數據如下: -

declare @jsonData Table (jsonText nvarchar(max))

insert into @jsonData(jsonText)values(N'{
    "username": "George84",
    "items": [{
            "type": 8625,
            "score": "90"
        }, {
            "type": 8418,
            "score": "84"
        }, {
            "type": 7818,
            "score": "90"
        }, {
            "type": 23,
            "score": "q"
        }
    ]
}'),(N'{
    "username": "George85",
    "items": [{
            "type": 8625,
            "score": "80"
        }, {
            "type": 8418,
            "score": "90"
        }, {
            "type": 7818,
            "score": "70"
        }, {
            "type": 232,
            "score": "q"
        }
    ]
}'),(N'{
    "username": "George86",
    "items": [{
            "type": 8626,
            "score": "80"
        }, {
            "type": 8418,
            "score": "70"
        }, {
            "type": 7818,
            "score": "90"
        }, {
            "type": 23,
            "score": "q"
        }
    ]
}'),(N'{
    "username": "George87",
    "items": [{
            "type": 8625,
            "score": "90"
        }, {
            "type": 8418,
            "score": "70"
        }, {
            "type": 7818,
            "score": "60"
        }, {
            "type": 23,
            "score": "q"
        }
    ]
}')

這會給我一個模擬主數據表的表。

讓我們創建一些內存表來存儲數據,如下所示:

declare @Users Table (ID int not null IDENTITY(1, 1),username nvarchar(50))
declare @Types Table (ID int not null IDENTITY(1, 1),[type] int)
declare @Scores Table (ID int not null IDENTITY(1, 1),score nvarchar(50))
declare @Items Table (ID int not null IDENTITY(1, 1),UserId int,TypeId int,ScoreId int)

您可能已經創建了上面的表,因此您可以替換它們。 所以讓我們跳轉到將填充表格的t-sql

declare @RowsCount int=(select count(*) from @jsonData)
declare @index int=1
declare @jsonRowData NVARCHAR(MAX)
declare @username NVARCHAR(50)

while(@index<=@RowsCount)
begin
    ;with JsonDataWithSeq as (
        select ROW_NUMBER() over(order by jsonText) [seq],* from @jsonData
    ) select top(1) @jsonRowData=JsonDataWithSeq.jsonText from JsonDataWithSeq where seq=@index

    --select @jsonRowData [jsonRowData],ISJSON(@jsonRowData)  [ISJSON]

    SELECT @username=JSON_VALUE(@jsonRowData, '$.username') 

    if not exists (select * from @Users where username=@username)--no need for this check if names are unique in the list
    insert into @Users (username) values(@username)

    insert into @Types([type])
    SELECT xx.[type] from OPENJSON(@jsonRowData, 'lax $.items') with ([type] int) xx where xx.[type] not in (select t.[type] From @Types t)

    insert into @Scores([score])
    SELECT xx.[score] from OPENJSON(@jsonRowData, 'lax $.items') with ([score] nvarchar(50)) xx where xx.[score] not in (select t.[score] From @Scores t)

    insert into @Items(UserId,TypeId,ScoreId)
    SELECT u.ID [UserID],t.ID [TypeID],s.ID [ScoreID]  from OPENJSON(@jsonRowData, 'lax $.items') with ([type] int,[score] nvarchar(50)) xx
    inner join @Users u on u.username=@username
    inner join @Types t on t.[type]=xx.[type]
    inner join @Scores s on s.score=xx.score

    set @index=@index+1
end

select * from @Users
select * from @Types
select * from @Scores
select * from @Items

就是這樣,希望這會有所幫助。

對於我提供的數據,我得到以下結果: -

用戶表: -

ID  username
==  ========
1   George84
2   George85
3   George86
4   George87

類型表: -

ID  type
==  =====
1   8625
2   8418
3   7818
4   23
5   232
6   8626

分數表: -

ID  score
==  ======
1   90
2   84
3   90
4   q
5   80
6   70
7   60

物品表: -

ID      UserId  TypeId  ScoreId
==      ====== =======  ========
1       1       1       1
2       1       1       3
3       1       2       2
4       1       3       1
5       1       3       3
6       1       4       4
7       2       1       5
8       2       2       1
9       2       2       3
10      2       3       6
11      2       5       4
12      3       6       5
13      3       2       6
14      3       3       1
15      3       3       3
16      3       4       4
17      4       1       1
18      4       1       3
19      4       2       6
20      4       3       7
21      4       4       4

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM