Arrays 使用SQL Server函数将JSON数组分解为子表
下面是我想使用SQL Server JSON函数将JSON分解为三个表:Arrays 使用SQL Server函数将JSON数组分解为子表,arrays,json,sql-server,Arrays,Json,Sql Server,下面是我想使用SQL Server JSON函数将JSON分解为三个表: { "school" : "Ecole", "classes": [ { "className": "Math", "Students": ["LaPlace", "Fourier","Euler","Pascal"] } { "className": "Science"
{
"school" : "Ecole",
"classes": [
{
"className": "Math",
"Students": ["LaPlace", "Fourier","Euler","Pascal"]
}
{
"className": "Science",
"Students": ["Newton", "Einstein","Al-Biruni", "Cai"]
},
]
}
Table 1
+-------+--------+
| ID | school |
+-------+--------+
Table 2
+-------+---------------+-----------+
| ID | schoolID (FK) | className |
+-------+---------------+-----------+
Table 3
+-------+---------------+-----------+
| ID | classID (FK) | student |
+-------+---------------+-----------+
到目前为止,我的问题是:
SELECT * FROM OPENJSON(@json, '$.school') --Returns the name of the school
SELECT
ClassName = JSON_VALUE(c.value, '$.className'),
Students = JSON_QUERY(c.value, '$.Students')
FROM
OPENJSON(@json, '$.classes') c
--返回类的名称和学生的JSON数组
我想知道如何使用SQL分解JSON数组来提取第三个表的数据,使其看起来像这样:
declare @json nvarchar(max) = N'
{
"school" : "Ecole",
"classes": [
{
"className": "Math",
"Students": ["LaPlace", "Fourier","Euler","Pascal"]
},
{
"className": "Science",
"Students": ["Newton", "Einstein","Al-Biruni", "Cai"]
}
]
}
';
with q as
(
SELECT
ClassID = c.[key]+1,
ClassName = JSON_VALUE(c.value, '$.className'),
Id = row_number() over (order by c.[Key], students.[key] ),
Student = students.value
FROM
OPENJSON(@json, '$.classes') c
cross apply openjson(c.value,'$.Students') students
)
select Id, ClassId, Student
from q
/*
Id ClassId Student
----------- ----------- -----------
1 1 LaPlace
2 1 Fourier
3 1 Euler
4 1 Pascal
5 2 Newton
6 2 Einstein
7 2 Al-Biruni
8 2 Cai
*/
数学类Id=1
科学课Id=2
Id ClassId Student
+-------+--------+-----------+
| 1 | 1 | LaPlace |
+-------+--------+-----------+
| 2 | 1 | Fourier |
+-------+--------+-----------+
| 3 | 1 | Euler |
+-------+--------+-----------+
| 4 | 1 | Pascal |
+-------+--------+-----------+
| 5 | 2 | Newton |
+-------+--------+-----------+
| 6 | 2 | Einstein |
+-------+--------+-----------+
| 7 | 2 | Al-Biruni |
+-------+--------+-----------+
| 8 | 2 | Cai |
+-------+--------+-----------+
我可以从其他表中获取ID,但我不知道如何编写查询来从JSON数组中提取学生
我确实能够重新构造JSON模式,这样我就可以创建对象数组,而不是字符串数组:
"Students": [{"StudentName"}:"Newton", {"StudentName":"Einstein"},{"StudentName":"Al-Biruni"}, {"StudentName":"Cai"}]
但我不确定这会让事情变得更容易。无论如何,我仍然想知道如何编写查询来完成第一个案例 类似这样:
declare @json nvarchar(max) = N'
{
"school" : "Ecole",
"classes": [
{
"className": "Math",
"Students": ["LaPlace", "Fourier","Euler","Pascal"]
},
{
"className": "Science",
"Students": ["Newton", "Einstein","Al-Biruni", "Cai"]
}
]
}
';
with q as
(
SELECT
ClassID = c.[key]+1,
ClassName = JSON_VALUE(c.value, '$.className'),
Id = row_number() over (order by c.[Key], students.[key] ),
Student = students.value
FROM
OPENJSON(@json, '$.classes') c
cross apply openjson(c.value,'$.Students') students
)
select Id, ClassId, Student
from q
/*
Id ClassId Student
----------- ----------- -----------
1 1 LaPlace
2 1 Fourier
3 1 Euler
4 1 Pascal
5 2 Newton
6 2 Einstein
7 2 Al-Biruni
8 2 Cai
*/
大概是这样的:
declare @json nvarchar(max) = N'
{
"school" : "Ecole",
"classes": [
{
"className": "Math",
"Students": ["LaPlace", "Fourier","Euler","Pascal"]
},
{
"className": "Science",
"Students": ["Newton", "Einstein","Al-Biruni", "Cai"]
}
]
}
';
with q as
(
SELECT
ClassID = c.[key]+1,
ClassName = JSON_VALUE(c.value, '$.className'),
Id = row_number() over (order by c.[Key], students.[key] ),
Student = students.value
FROM
OPENJSON(@json, '$.classes') c
cross apply openjson(c.value,'$.Students') students
)
select Id, ClassId, Student
from q
/*
Id ClassId Student
----------- ----------- -----------
1 1 LaPlace
2 1 Fourier
3 1 Euler
4 1 Pascal
5 2 Newton
6 2 Einstein
7 2 Al-Biruni
8 2 Cai
*/
从SQL Server 2016开始支持JSON 由于您的JSON嵌套更深(类数组包含学生数组),我将结合使用
OPENJSON
和with
-子句来解决这个问题。请在WITH
-子句中更靠近AS JSON
。这将允许另一个交叉应用OPENJSON()
,从而越来越深入到JSON结构中
DECLARE @json NVARCHAR(MAX) =
N'{
"school" : "Ecole",
"classes": [
{
"className": "Math",
"Students": ["LaPlace", "Fourier","Euler","Pascal"]
},
{
"className": "Science",
"Students": ["Newton", "Einstein","Al-Biruni", "Cai"]
}
]
}';
--询问
SELECT ROW_NUMBER() OVER(ORDER BY B.className,C.[key]) AS RowId
,A.school
,B.className
,CASE B.className WHEN 'Math' THEN 1 WHEN 'Science' THEN 2 ELSE 0 END AS ClassId
,C.[key] AS StudentIndex
,C.[value] AS Student
FROM OPENJSON(@json)
WITH(school NVARCHAR(MAX)
,classes NVARCHAR(MAX) AS JSON) A
CROSS APPLY OPENJSON(A.classes)
WITH(className NVARCHAR(MAX)
,Students NVARCHAR(MAX) AS JSON) B
CROSS APPLY OPENJSON(B.Students) C
结果
+-------+--------+-----------+---------+--------------+-----------+
| RowId | school | className | ClassId | StudentIndex | Student |
+-------+--------+-----------+---------+--------------+-----------+
| 1 | Ecole | Math | 1 | 0 | LaPlace |
+-------+--------+-----------+---------+--------------+-----------+
| 2 | Ecole | Math | 1 | 1 | Fourier |
+-------+--------+-----------+---------+--------------+-----------+
| 3 | Ecole | Math | 1 | 2 | Euler |
+-------+--------+-----------+---------+--------------+-----------+
| 4 | Ecole | Math | 1 | 3 | Pascal |
+-------+--------+-----------+---------+--------------+-----------+
| 5 | Ecole | Science | 2 | 0 | Newton |
+-------+--------+-----------+---------+--------------+-----------+
| 6 | Ecole | Science | 2 | 1 | Einstein |
+-------+--------+-----------+---------+--------------+-----------+
| 7 | Ecole | Science | 2 | 2 | Al-Biruni |
+-------+--------+-----------+---------+--------------+-----------+
| 8 | Ecole | Science | 2 | 3 | Cai |
+-------+--------+-----------+---------+--------------+-----------+
从SQL Server 2016开始支持JSON 由于您的JSON嵌套更深(类数组包含学生数组),我将结合使用
OPENJSON
和with
-子句来解决这个问题。请在WITH
-子句中更靠近AS JSON
。这将允许另一个交叉应用OPENJSON()
,从而越来越深入到JSON结构中
DECLARE @json NVARCHAR(MAX) =
N'{
"school" : "Ecole",
"classes": [
{
"className": "Math",
"Students": ["LaPlace", "Fourier","Euler","Pascal"]
},
{
"className": "Science",
"Students": ["Newton", "Einstein","Al-Biruni", "Cai"]
}
]
}';
--询问
SELECT ROW_NUMBER() OVER(ORDER BY B.className,C.[key]) AS RowId
,A.school
,B.className
,CASE B.className WHEN 'Math' THEN 1 WHEN 'Science' THEN 2 ELSE 0 END AS ClassId
,C.[key] AS StudentIndex
,C.[value] AS Student
FROM OPENJSON(@json)
WITH(school NVARCHAR(MAX)
,classes NVARCHAR(MAX) AS JSON) A
CROSS APPLY OPENJSON(A.classes)
WITH(className NVARCHAR(MAX)
,Students NVARCHAR(MAX) AS JSON) B
CROSS APPLY OPENJSON(B.Students) C
结果
+-------+--------+-----------+---------+--------------+-----------+
| RowId | school | className | ClassId | StudentIndex | Student |
+-------+--------+-----------+---------+--------------+-----------+
| 1 | Ecole | Math | 1 | 0 | LaPlace |
+-------+--------+-----------+---------+--------------+-----------+
| 2 | Ecole | Math | 1 | 1 | Fourier |
+-------+--------+-----------+---------+--------------+-----------+
| 3 | Ecole | Math | 1 | 2 | Euler |
+-------+--------+-----------+---------+--------------+-----------+
| 4 | Ecole | Math | 1 | 3 | Pascal |
+-------+--------+-----------+---------+--------------+-----------+
| 5 | Ecole | Science | 2 | 0 | Newton |
+-------+--------+-----------+---------+--------------+-----------+
| 6 | Ecole | Science | 2 | 1 | Einstein |
+-------+--------+-----------+---------+--------------+-----------+
| 7 | Ecole | Science | 2 | 2 | Al-Biruni |
+-------+--------+-----------+---------+--------------+-----------+
| 8 | Ecole | Science | 2 | 3 | Cai |
+-------+--------+-----------+---------+--------------+-----------+
JSON_值和openjson在哪个版本的SQL Server.SQL Server 2016+和Azure SQL数据库中工作。David,谢谢!你能推荐一个好的资源来学习更多关于SQL的知识,包括查询JSON的新功能吗?这里是“官方”中心,虽然也有大量的第三方内容。JSON_值和openjson在哪个版本的SQL Server.SQL Server 2016+和Azure SQL数据库中工作。David,谢谢!你能推荐一个好的资源来学习更多关于SQL的知识,包括查询JSON的新功能吗?这里是“官方”中心,虽然也有大量的第三方内容。这也是一个好答案,因为案例可用于设置数学和科学ID的其他值。这也是一个好答案,因为案例可用于设置数学和科学ID的其他值。