请你帮我把FOR LOOP查询中的以下查询重写为单循环查询:
for rec in select distinct sp.student_id, v.test_id, v.name, p.version_id from student_pages sp, pages p, versions v where p.id = sp.page_id and v.id = p.version_id order by student_id, test_id, name LOOP
select STRING_AGG(cast(p.index as varchar), ';' ORDER BY p.index) as lost_page_indices into l_lost_page_indices from pages p left join student_pages sp on p.id = sp.page_id and sp.student_id = rec.student_id where p.version_id = rec.version_id and sp.page_id is null;
end loop;
在最终查询中,我需要以下字段:sp.student_id,v.test_id,v.name和lost_page_indices。
答案 0 :(得分:1)
首先剪切:接受您循环的查询,将其转换为子查询,并将其用作连接表。
select STRING_AGG(cast(p.index as varchar), ';' ORDER BY p.index)
as lost_page_indices into l_lost_page_indices
from pages p
join (
select distinct sp.student_id, v.test_id, v.name, p.version_id
from student_pages sp
join pages p on p.id = sp.page_id
join versions v on v.id = p.version_id
) as rec on rec.student_id = sp.student_id
left join student_pages sp on p.id = sp.page_id and
sp.student_id = rec.student_id
where p.version_id = rec.version_id and
sp.page_id is null
order by rec.student_id, rec.test_id, rec.name
我使用连接语法重新生成子查询以便于阅读。
不能依赖 order by
来保持连接,因此它会进入外部查询。
没有group by
所以我不确定聚合函数是否有效。
正如其他人所指出的,string_agg()
is not a built in Oracle function。你必须自己做。
这可以简化,两个连接之间有很多冗余。该子查询将student_pages,页面和版本放在一起,这些都可以通过普通连接完成。唯一剩下的就是distinct sp.student_id
,使用group by sp.student_id
可以做得更好。
select STRING_AGG(cast(p.index as varchar), ';' ORDER BY p.index)
as lost_page_indices into l_lost_page_indices
from pages p
left join student_pages sp on sp.page_id = p.id
join versions v on v.id = p.version_id
where sp.page_id is null
group by sp.student_id
order by sp.student_id, v.test_id, v.name
我并非100%确定它是一个等效的查询,但它应该让你开始。这使查询更加清晰:查找孤立的页面并将它们粘贴到表中。