将FOR LOOP中的查询重写为单个查询

时间:2016-10-14 22:34:56

标签: sql oracle loops for-loop subquery

请你帮我把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。

1 个答案:

答案 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%确定它是一个等效的查询,但它应该让你开始。这使查询更加清晰:查找孤立的页面并将它们粘贴到表中。