我正在尝试使用针对Oracle JSON数据结构的路径表达式编写一个简单查询,该结构将返回学生姓名及其CS220教师的姓名(如果他们正在学习该课程)。
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
我找到的唯一解决方案是将嵌套的“类”投影到表中,并将其连接到上面的查询以获取教授。我原以为Oracle的json路径实现能够在没有第二个查询的开销/复杂性的情况下解决这个问题。
答案 0 :(得分:2)
在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
表示每个班级(每个学生)获得一行,并附有相关的班级名称和教师姓名。
然后,选择列表使用案例表达式将教师名称更改为任何其他类的null - 因此John Smith获得一行CS220和Jason Wu,以及一行CS115和null。将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
添加聚合步骤:
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;
在12cR2中我 想想想到你可能会做这样的事情,在JSON路径中有一个过滤器(在12cR1中不允许这样做) ):
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.1/css/bulma.min.css">
<div>
<span class="icon">
<i class="fa fa-home"></i>
</span>
<span>ICON</span>
</div>
...但我没有合适的数据库来测试它。
...但事实证明,获得&#34; ORA-40553:此操作中不支持谓词的路径表达式&#34;和&#34;只有JSON_EXISTS支持谓词&#34;。