这里是JSON,我想使用SQL Server JSON函数切成三个表:
{
"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数组以提取第三张表的数据,使其看起来像这样:
数学类别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"}]
但是我不确定这会变得更容易。无论哪种方式,我仍然想知道如何编写查询以完成第一种情况。
答案 0 :(得分:2)
JSON
。
由于您的JSON更深层嵌套(类数组包含一个学生数组),我将结合OPENJSON
和WITH
子句来解决此问题。请稍微靠近AS JSON
子句中的WITH
。这将允许另一个CROSS APPLY 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 |
+-------+--------+-----------+---------+--------------+-----------+
答案 1 :(得分:1)
类似这样的东西:
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
*/