2013-05-30 4 views
0

Я делаю несколько тестов, чтобы проверить, могу ли я ускорить определенный набор результатов, но не могу заставить это конкретное решение работать. У меня есть данные, поступающие в несколько разных таблиц, и вы хотите объединить данные. Я хочу попробовать это, не используя объединение, чтобы увидеть, улучшилось ли качество.oracle получается из таблиц с использованием функции

Когда у меня есть пользовательский тип таблицы/объекта в функции, кажется, что удаляются существующие данные из таблицы при последующем выборе. Есть ли способ сделать последующие выборки в таблице без удаления предыдущих данных?

SQL Fiddle

+2

Вы все равно будете делать два выбора с добавлением контекстного переключателя в PL/SQL, поэтому не знаете, почему вы ожидаете, что он будет быстрее. Единственное существенное различие заключается в том, что вы избегаете сортировки для удаления дубликатов, что также можно избежать с помощью оригинала, используя 'union all'. –

ответ

2

Я не думаю, что такой подход будет быстрее, на самом деле я ожидаю, что это будет гораздо медленнее.

Но если вы хотите это сделать, вам нужно поместить строки из второго выбора в промежуточную коллекцию, а затем присоединиться к обоим, используя multiset union.

Что-то вроде этого:

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; 
/
0

Как мультимножество подход, если вы действительно хотите сделать это, вы также могли бы сделать это 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; 

SQL Fiddle.

+0

Я смотрел на конвейерную функцию. Я предположил, что мой возвращенный набор данных 30-50 строк будет достаточно мал, чтобы не понадобиться. Но это все еще очень информативно. Спасибо. – Gordolio

0

Спасибо a_horse_with_no_name за указание, что выполнение нескольких выборок по одному будет, вероятно, медленнее. Я смог сократить время выполнения, отфильтруя каждый select by student_id, а затем объединив (а не объединяя все, а затем фильтруя). На наборе данных я работаю с этим решением был самым быстрым с менее чем 1/10 секунды ...

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)); 

и это заняло 2-3 секунды для выполнения ...

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; 

SQLFiddle.

Смежные вопросы