2016-10-14 1 views
0

Не могли бы вы мне помочь переписать следующий запрос внутри 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; 

В последнем запросе мне нужно следующие поля: зр .student_id, v.test_id, v.name и lost_page_indices.

+1

В Oracle не существует 'string_agg()') –

+0

Вау, это какая-то работающая инструкция, которая у вас есть. Что происходит с предложениями FROM и WHERE после 'in l_lost_page_indices'? Лучше всего начать: описать три базовые таблицы ('student_pages и т. Д.) - показать имена столбцов и типы данных (ОК, чтобы включать только соответствующие столбцы), обозначения первичного и внешнего ключей, а не нулевые ограничения, а затем, что вы пытаетесь сделать. Объясните на английском языке, укажите небольшую выборку входных данных и желаемый результат; не нужно пытаться помещать его в запрос, мы можем с этим помочь. – mathguy

+1

Весь цикл выглядит слишком сложно. Вместо того, чтобы просто переписать цикл, было бы лучше, если бы вы сказали нам, в чем проблема, которую вы пытаетесь решить. Покажите нам свою структуру таблицы, некоторые примеры данных и ожидаемый результат. –

ответ

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. Вы должны сделать это сами.


Это может быть упрощено, существует много избыточности между двумя соединениями. Этот подзапрос объединяет студенческие страницы, страницы и версии, которые могут быть выполнены с помощью обычного соединения. Осталось только 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% уверен, что это эквивалентный запрос, но он должен вас начать. Это делает намного более понятным, что делает запрос: найти осиротые страницы и вставить их в таблицу.

+0

Спасибо большое!) Единственное условие заключается в том, что условие соединения должно быть: pages p internal join rec on rec.version_id = p.version_id вместо rec.student_id = sp.student_id – MaterialGirl

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