在 JSON 个数组上使用 Oracle 路径表达式
Using Oracle Path Expressions on JSON arrays
我正在尝试针对 Oracle JSON 数据结构编写一个带有路径表达式的简单查询,该查询将 return 学生姓名和他们的 CS220 老师的姓名(如果他们正在参加class).
JSON:
{
'studentName': 'John Smith',
'classes': [
{
'className': 'CS115',
'teacherName': 'Sally Wilson'
},
{
'className': 'CS220',
'teacherName': 'Jason Wu'
}
]
}
预期输出
Student Name Professor
John Smith Jason Wu
Jane Doe << Not taking CS220
Ajay Kumar Robert Kroll
我希望写的查询:
Select
jsonfield.studentName,
jsonfield.classes.<some path expression to find the CS220 professor here>
from mytable
我找到的唯一解决方案是将嵌套的 'classes' 投射到 table 并将其加入上面的查询以获取教授。我原以为 Oracle 的 json 路径实现能够在没有第二个查询的 overhead/complexity 的情况下解决这个问题。
在 12cR1 中,您可以执行以下操作:
select jt.studentname,
max(case when jt.classname = 'CS220' then jt.teachername end) as teachername
from mytable mt
cross join json_table (
mt.jsonfield,
'$'
columns (
studentname varchar2(30) path '$.studentName',
nested path '$.classes[*]' columns (
classname varchar2(30) path '$.className',
teachername varchar2(30) path '$.teacherName'
)
)
) jt
group by jt.studentname;
json_table()
将 JSON 拆分为关系列; nested path
表示每个 class(每个学生)获得一行,其中包含相关的 class 姓名和教师姓名。
然后 select 列表使用 case 表达式将任何其他 classes 的教师姓名更改为 null - 因此 John Smith 获得 CS220 和 Jason Wu 的一行,以及 CS220 和 Jason Wu 的一行CS115 和空。将其与 max()
合计会折叠这些内容,因此所有不相关的教师都将被忽略。
使用一些扩展示例数据:
create table mytable (jsonfield clob check (jsonfield is json));
insert into mytable a(jsonfield) values (q'#{
'studentName': 'John Smith',
'classes': [
{
'className': 'CS115',
'teacherName': 'Sally Wilson'
},
{
'className': 'CS220',
'teacherName': 'Jason Wu'
}
]
}#');
insert into mytable a(jsonfield) values (q'#{
'studentName': 'Jane Doe',
'classes': [
{
'className': 'CS115',
'teacherName': 'Sally Wilson'
}
]
}#');
insert into mytable a(jsonfield) values (q'#{
'studentName': 'Ajay Kumar',
'classes': [
{
'className': 'CS220',
'teacherName': 'Robert Kroll'
}
]
}#');
基本 json_table()
调用得到:
select jt.*,
case when jt.classname = 'CS220' then jt.teachername end as adjusted_teachername
from mytable mt
cross join json_table (
mt.jsonfield,
'$'
columns (
studentname varchar2(30) path '$.studentName',
nested path '$.classes[*]' columns (
classname varchar2(30) path '$.className',
teachername varchar2(30) path '$.teacherName'
)
)
) jt;
STUDENTNAME CLASSNAME TEACHERNAME ADJUSTED_TEACHERNAME
------------------------------ ------------------------------ ------------------------------ ------------------------------
John Smith CS115 Sally Wilson
John Smith CS220 Jason Wu Jason Wu
Jane Doe CS115 Sally Wilson
Ajay Kumar CS220 Robert Kroll Robert Kroll
添加聚合步骤得到:
select jt.studentname,
max(case when jt.classname = 'CS220' then jt.teachername end) as teachername
from mytable mt
cross join json_table (
mt.jsonfield,
'$'
columns (
studentname varchar2(30) path '$.studentName',
nested path '$.classes[*]' columns (
classname varchar2(30) path '$.className',
teachername varchar2(30) path '$.teacherName'
)
)
) jt
group by jt.studentname;
STUDENTNAME TEACHERNAME
------------------------------ ------------------------------
John Smith Jason Wu
Jane Doe
Ajay Kumar Robert Kroll
在 12cR2 中,我 think thought 你也许可以做这样的事情,在 JSON 路径(这在 12cR1 中是不允许的):
select jt.*
from mytable mt
cross join json_table (
mt.jsonfield,
'$'
columns (
studentname varchar2(30) path '$.studentName',
nested path '$.classes[*]?(@.className=="CS220")' columns (
teachername varchar2(30) path '$.teacherName'
)
)
) jt;
...但是我没有合适的数据库来测试它。
...但结果是 "ORA-40553: path expression with predicates not supported in this operation" 和 "Only JSON_EXISTS supports predicates".
我正在尝试针对 Oracle JSON 数据结构编写一个带有路径表达式的简单查询,该查询将 return 学生姓名和他们的 CS220 老师的姓名(如果他们正在参加class).
JSON:
{
'studentName': 'John Smith',
'classes': [
{
'className': 'CS115',
'teacherName': 'Sally Wilson'
},
{
'className': 'CS220',
'teacherName': 'Jason Wu'
}
]
}
预期输出
Student Name Professor
John Smith Jason Wu
Jane Doe << Not taking CS220
Ajay Kumar Robert Kroll
我希望写的查询:
Select
jsonfield.studentName,
jsonfield.classes.<some path expression to find the CS220 professor here>
from mytable
我找到的唯一解决方案是将嵌套的 'classes' 投射到 table 并将其加入上面的查询以获取教授。我原以为 Oracle 的 json 路径实现能够在没有第二个查询的 overhead/complexity 的情况下解决这个问题。
在 12cR1 中,您可以执行以下操作:
select jt.studentname,
max(case when jt.classname = 'CS220' then jt.teachername end) as teachername
from mytable mt
cross join json_table (
mt.jsonfield,
'$'
columns (
studentname varchar2(30) path '$.studentName',
nested path '$.classes[*]' columns (
classname varchar2(30) path '$.className',
teachername varchar2(30) path '$.teacherName'
)
)
) jt
group by jt.studentname;
json_table()
将 JSON 拆分为关系列; nested path
表示每个 class(每个学生)获得一行,其中包含相关的 class 姓名和教师姓名。
然后 select 列表使用 case 表达式将任何其他 classes 的教师姓名更改为 null - 因此 John Smith 获得 CS220 和 Jason Wu 的一行,以及 CS220 和 Jason Wu 的一行CS115 和空。将其与 max()
合计会折叠这些内容,因此所有不相关的教师都将被忽略。
使用一些扩展示例数据:
create table mytable (jsonfield clob check (jsonfield is json));
insert into mytable a(jsonfield) values (q'#{
'studentName': 'John Smith',
'classes': [
{
'className': 'CS115',
'teacherName': 'Sally Wilson'
},
{
'className': 'CS220',
'teacherName': 'Jason Wu'
}
]
}#');
insert into mytable a(jsonfield) values (q'#{
'studentName': 'Jane Doe',
'classes': [
{
'className': 'CS115',
'teacherName': 'Sally Wilson'
}
]
}#');
insert into mytable a(jsonfield) values (q'#{
'studentName': 'Ajay Kumar',
'classes': [
{
'className': 'CS220',
'teacherName': 'Robert Kroll'
}
]
}#');
基本 json_table()
调用得到:
select jt.*,
case when jt.classname = 'CS220' then jt.teachername end as adjusted_teachername
from mytable mt
cross join json_table (
mt.jsonfield,
'$'
columns (
studentname varchar2(30) path '$.studentName',
nested path '$.classes[*]' columns (
classname varchar2(30) path '$.className',
teachername varchar2(30) path '$.teacherName'
)
)
) jt;
STUDENTNAME CLASSNAME TEACHERNAME ADJUSTED_TEACHERNAME
------------------------------ ------------------------------ ------------------------------ ------------------------------
John Smith CS115 Sally Wilson
John Smith CS220 Jason Wu Jason Wu
Jane Doe CS115 Sally Wilson
Ajay Kumar CS220 Robert Kroll Robert Kroll
添加聚合步骤得到:
select jt.studentname,
max(case when jt.classname = 'CS220' then jt.teachername end) as teachername
from mytable mt
cross join json_table (
mt.jsonfield,
'$'
columns (
studentname varchar2(30) path '$.studentName',
nested path '$.classes[*]' columns (
classname varchar2(30) path '$.className',
teachername varchar2(30) path '$.teacherName'
)
)
) jt
group by jt.studentname;
STUDENTNAME TEACHERNAME
------------------------------ ------------------------------
John Smith Jason Wu
Jane Doe
Ajay Kumar Robert Kroll
在 12cR2 中,我 think thought 你也许可以做这样的事情,在 JSON 路径(这在 12cR1 中是不允许的):
select jt.*
from mytable mt
cross join json_table (
mt.jsonfield,
'$'
columns (
studentname varchar2(30) path '$.studentName',
nested path '$.classes[*]?(@.className=="CS220")' columns (
teachername varchar2(30) path '$.teacherName'
)
)
) jt;
...但是我没有合适的数据库来测试它。
...但结果是 "ORA-40553: path expression with predicates not supported in this operation" 和 "Only JSON_EXISTS supports predicates".