Reputation: 1997
I'm doing some testing to see if I can speed up a particular result set, but can't seem to get this particular solution working. I have data coming a few different tables and want to combine the data. I want to try this without using a union select to see if I get a performance improvement.
When I have a custom table/object type in a function, it seems to delete the existing data from the table when doing the subsequent select. Is there a way to do subsequent selects into the table without having the previous data deleted?
Upvotes: 0
Views: 78
Reputation: 1997
Thanks a_horse_with_no_name for pointing out that doing the multiple selects one at a time will probably be slower. I was able to reduce the execution time by filtering each select by student_id and then union-ing (rather than union-ing everything then filtering). On the data set I'm working with this solution was the fastest taking less than 1/10 of a second...
create or replace function
academic_history(p_student_id number)
return ah_tab_type
is
T ah_tab_type;
begin
select ah_obj_type(student_id,course_code,grade)
bulk collect
into T
from (
select student_id,course_code,grade
from completed_courses
where student_id = p_student_id
union
select student_id,course_code,'P'
from trans_courses
where student_id = p_student_id);
return T;
end;
/
select *
from table(academic_history(1));
and this took 2-3 seconds to execute...
create view vw_academic_history
select student_id,course_code,grade
from completed_courses
union
select student_id,course_code,'P'
from trans_courses;
select *
from vw_academic_history
where student_id = 1;
Upvotes: 0
Reputation: 191570
As well as the multiset approach, if you really wanted to do this you could also make it a pipelined function:
create or replace function
academic_history(p_student_id number)
return ah_tab_type pipelined
is
T ah_tab_type;
begin
select ah_obj_type(student_id,course_code,grade)
bulk collect
into T
from completed_courses
where student_id = p_student_id;
for i in 1..T.count loop
pipe row (T(i));
end loop;
select ah_obj_type(student_id,course_code,'P')
bulk collect
into T
from trans_courses
where student_id = p_student_id;
for i in 1..T.count loop
pipe row (T(i));
end loop;
return;
end;
Upvotes: 0
Reputation:
I don't think that approach will be faster, in fact I expect it to be much slower.
But if you do want to do it, you need to put the rows from the second select into an intermediate collection and then join both using multiset union
.
Something like this:
create or replace function
academic_history(p_student_id number)
return ah_tab_type
is
result ah_tab_type;
t ah_tab_type;
begin
select ah_obj_type(student_id,course_code,grade)
bulk collect into result
from completed_courses
where student_id = p_student_id;
select ah_obj_type(student_id,course_code,'P')
bulk collect into T
from trans_courses
where student_id = p_student_id;
result := result multiset union t;
return result;
end;
/
Upvotes: 2